我似乎无法理解如何构建对SendPingAsync的异步调用。我想遍历 IP 地址列表并在继续程序之前异步 ping 它们......现在,一次完成所有这些需要很长时间。我之前问了一个关于它的问题,以为我能够弄清楚异步,但显然我错了。
private void button1_Click(object sender, EventArgs e)
{
this.PingLoop();
MessageBox.Show("hi"); //for testing
}
public async void PingLoop()
{
Task<int> 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<int> 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<List<PingReply>> PingAsync()
{
var tasks = theListOfIPs.Select(ip => new Ping().SendPingAsync(ip, 2000));
var results = await Task.WhenAll(tasks);
return results.ToList();
}
这将异步启动每个 IP theListOfIPs
的一个请求,然后异步等待它们全部完成。 然后,它将返回回复列表。
请注意,返回结果几乎总是比在字段中设置结果更好。 如果您在异步操作完成之前使用该字段 (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<PingReply> pingAsync(IPAddress ipaddress)
{
var tcs = new TaskCompletionSource<PingReply>();
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;
}
在后台工作者中我这样做
List<Task<PingReply>> pingTasks = new List<Task<PingReply>>();
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);
}
public static async Task<bool> PingAsync(string host)
{
try
{
var ping = new System.Net.NetworkInformation.Ping();
var reply = await ping.SendTaskAsync(host);
return (reply.Status == System.Net.NetworkInformation.IPStatus.Success);
}
catch { return false; }
}