How to Perform Multiple "Pings" in Parallel using C#
The ping class has a method SendAsync
. This follows the Event-based Asynchronous Programming (EAP) pattern. Check out this article: http://msdn.microsoft.com/en-us/library/ee622454.aspx.
For a quick example here is a method I have that implements that article in a very basic fashion. You can basically call this as many times as you want and all the pings will be done asychronously.
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;
}
}
use the Parallel.For and a 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");
}
// The solution becomes simpler using LINQ
List<String> hosts = new List<String>();
for (Int32 i = 0; i < 100; ++i) hosts.Add("www.google.com");
var average = hosts.AsParallel().WithDegreeOfParallelism(64).
Select(h => new Ping().Send(h).RoundtripTime).Average();
Console.WriteLine(average)