如何使用C#并行执行多个"Ping"

Hyd*_*per 12 c# multithreading ping

我试图计算一组服务器的平均往返时间.为了加快速度,我想并行执行ping操作.我已经写了一个函数调用AverageRoundtripTime()它似乎工作,但是,因为我不太了解多线程,我想知道我做了什么是好的.请查看我的代码并让我知道它是否正常或是否有更好的方法来实现我想要的:

public void Main()
{
    // Collection of hosts.
    List<String> hosts = new List<String>();

    // Add 100 hosts to the collection.
    for (Int32 i = 0; i < 100; ++i) hosts.Add("www.google.com");

    // Display the average round-trip time for 100 hosts.
    Console.WriteLine(AverageRoundtripTime(hosts));

}

public Double AverageRoundtripTime(IEnumerable<String> hosts)
{
    // Collection of threads.
    List<Thread> threads = new List<Thread>();

    // Collection of ping replies.
    List<PingReply> pingReplies = new List<PingReply>();

    // Loop through all host names.
    foreach (var host in hosts)
    {
        // Create a new thread.
        Thread thread = new Thread(() =>
        {
            // Variable to hold the ping reply.
            PingReply reply = null;

            // Create a new Ping object and make sure that it's 
            // disposed after we're finished with it.
            using (Ping ping = new Ping())
            {
                    reply = ping.Send(host);

            }

            // Get exclusive lock on the pingReplies collection.
            lock (pingReplies)
            {
                // Add the ping reply to the collection.
                pingReplies.Add(reply);

            }

        });

        // Add the newly created thread to the theads collection.
        threads.Add(thread);

        // Start the thread.
        thread.Start();

    }

    // Wait for all threads to complete
    foreach (Thread thread in threads)
    {
        thread.Join();

    }

    // Calculate and return the average round-trip time.
    return pingReplies.Average(x => x.RoundtripTime);

}
Run Code Online (Sandbox Code Playgroud)

更新:

查看我问过的相关问题:

Windows窗体应用程序中的任务并行库代码冻结 - 作为Windows控制台应用程序正常工作

Pet*_*ete 13

ping类有一个方法SendAsync.这遵循基于事件的异步编程(EAP)模式.看看这篇文章:http://msdn.microsoft.com/en-us/library/ee622454.aspx.

这里有一个快速的例子,我有一个以非常基本的方式实现该文章的方法.您基本上可以根据需要多次调用它,并且所有ping都将异步完成.

    class Program
    {
    public static string[] addresses = {"microsoft.com", "yahoo.com", "google.com"};
    static void Main(string[] args)
    {
        List<Task<PingReply>> pingTasks = new List<Task<PingReply>>();
        foreach (var address in addresses)
        {
            pingTasks.Add(PingAsync(address));
        }

        //Wait for all the tasks to complete
        Task.WaitAll(pingTasks.ToArray());

        //Now you can iterate over your list of pingTasks
        foreach (var pingTask in pingTasks)
        {
            //pingTask.Result is whatever type T was declared in PingAsync
            Console.WriteLine(pingTask.Result.RoundtripTime);
        }
        Console.ReadLine();
    }

    static Task<PingReply> PingAsync(string address)
    {
        var tcs = new TaskCompletionSource<PingReply>();
        Ping ping = new Ping();
        ping.PingCompleted += (obj, sender) =>
            {
                tcs.SetResult(sender.Reply);
            };
        ping.SendAsync(address, new object());
        return tcs.Task;
    }
}
Run Code Online (Sandbox Code Playgroud)


agr*_*adl 5

使用 Parallel.For 和 ConcurrentBag

    static void Main(string[] args)
    {
        Console.WriteLine(AverageRoundTripTime("www.google.com", 100));
        Console.WriteLine(AverageRoundTripTime("www.stackoverflow.com", 100));
        Console.ReadKey();
    }

    static double AverageRoundTripTime(string host, int sampleSize)
    {
        ConcurrentBag<double> values = new ConcurrentBag<double>();
        Parallel.For(1, sampleSize, (x, y) => values.Add(Ping(host)));
        return values.Sum(x => x) / sampleSize;
    }
    static double Ping(string host)
    {
        var reply = new Ping().Send(host);
        if (reply != null)
            return reply.RoundtripTime;
        throw new Exception("denied");
    }
Run Code Online (Sandbox Code Playgroud)