如何同时异步进行多次ping操作?

我似乎无法理解如何构建对SendPingAsync的异步调用。 我想循环遍历一个IP地址列表,并在继续执行程序之前异步ping它们…现在需要一次一个地遍历所有这些地址。 我之前问了一个关于它的问题,我认为我能够找出异步,但显然我错了。

private void button1_Click(object sender, EventArgs e) { this.PingLoop(); MessageBox.Show("hi"); //for testing } public async void PingLoop() { Task longRunningTask = PingAsync(); int result = await longRunningTask; MessageBox.Show("async call is finished!"); //eventually want to loop here but for now just want to understand how this works } private async Task PingAsync() { Ping pingSender = new Ping(); string reply = pingSender.SendPingAsync("www.google.com", 2000).ToString(); pingReplies.Add(reply); //what should i be awaiting here?? return 1; } 

我恐怕只是不知道这里到底发生了什么……我应该什么时候回来? 当我按原样运行时,我只是获得了冻结的UI和ping错误。 我已经阅读了MSDN文档和大量问题,我只是没有得到它。

你想做的事情如下:

 private async Task> PingAsync() { Ping pingSender = new Ping(); var tasks = theListOfIPs.Select(ip => pingSender.SendPingAsync(ip, 2000)); var results = await Task.WhenAll(tasks); return results.ToList(); } 

这将异步启动theListOfIPs每个IP的一个请求,然后异步等待它们全部完成。 然后它将返回回复列表。

请注意,返回结果与在字段中设置结果几乎总是更好。 如果你在异步操作完成之前使用字段( pingReplies ),后者可能会导致错误 – 通过返回,并在使用await进行调用后将范围添加到集合中,可以使代码更清晰,更容易出错。

你在这里做什么pingSender.SendPingAsync("www.google.com", 2000).ToString(); 没有多大意义。

相反,你应该返回pingSender.SendPingAsync("www.google.com", 2000)

await Task.WhenAll(your all ping requests)

你想要的是立即开始所有ping:

 var pingTargetHosts = ...; //fill this in var pingTasks = pingTargetHosts.Select( host => new Ping().SendPingAsync(host, 2000)).ToList(); 

现在ping正在运行。 收集他们的结果:

 var pingResults = await Task.WhenAll(pingTasks); 

现在,处理的并发阶段已完成,您可以检查并处理结果。

我就是这样做的

 private delegate void scanTargetDelegate(IPAddress ipaddress); private Task pingAsync(IPAddress ipaddress) { var tcs = new TaskCompletionSource(); try { AutoResetEvent are = new AutoResetEvent(false); Ping ping = new Ping(); ping.PingCompleted += (obj, sender) => { tcs.SetResult(sender.Reply); }; ping.SendAsync(ipaddress, new object { }); } catch (Exception) { } return tcs.Task; } 

在BackgroundWorker中我这样做

 List> pingTasks = new List>(); addStatus("Scanning Network"); foreach (var ip in range) { pingTasks.Add(pingAsync(ip)); } Task.WaitAll(pingTasks.ToArray()); addStatus("Network Scan Complete"); scanTargetDelegate d = null; IAsyncResult r = null; foreach (var pingTask in pingTasks) { if (pingTask.Result.Status.Equals(IPStatus.Success)) { d = new scanTargetDelegate(scanTarget); //do something with the ip r = d.BeginInvoke(pingTask.Result.Address, null, null); Interlocked.Increment(ref Global.queuedThreads); } else { if (!ownIPs.Contains(pingTask.Result.Address)) { failed.Add(pingTask.Result.Address); } } } if (r != null) { WaitHandle[] waits = new WaitHandle[] { r.AsyncWaitHandle }; WaitHandle.WaitAll(waits); }