C# 为什么WhenAll会用多个ping不确定地等待?
我的应用程序需要ping网络中所有可能的IP地址。由于IP列表很大(大约4000个条目),我决定异步执行ping以加快进程。我最初编写的代码似乎工作得很好,但不知何故,当我昨天尝试它时,它不再像预期的那样工作了(可能是在一些.NET更新之后?我真的不知道) 我的代码是这样工作的:从IP地址列表中,我创建了一个任务列表(每个IP一个),然后将任务列表传递给WhenAll,等待所有ping请求完成。问题是有时WhenAll会无限期地等待(我用调试器检查了它,发现传递给WhenAll的一些任务始终处于“等待激活”状态)。奇怪的是,有时(在3次测试中大约2次)它会按预期工作,并且所有任务都会完成 以下是我使用的代码:C# 为什么WhenAll会用多个ping不确定地等待?,c#,.net,multithreading,ping,C#,.net,Multithreading,Ping,我的应用程序需要ping网络中所有可能的IP地址。由于IP列表很大(大约4000个条目),我决定异步执行ping以加快进程。我最初编写的代码似乎工作得很好,但不知何故,当我昨天尝试它时,它不再像预期的那样工作了(可能是在一些.NET更新之后?我真的不知道) 我的代码是这样工作的:从IP地址列表中,我创建了一个任务列表(每个IP一个),然后将任务列表传递给WhenAll,等待所有ping请求完成。问题是有时WhenAll会无限期地等待(我用调试器检查了它,发现传递给WhenAll的一些任务始终处于
public static async Task<List<PingReply>> PingAsync(List<IPAddress> ips, int timeout)
{
var pingTasks = ips.Select(ip =>
{
using (Ping ping = new Ping())
{
return ping.SendPingAsync(ip, timeout);
}
});
var results = await Task.WhenAll(pingTasks);
return results.ToList();
}
公共静态异步任务PingAsync(列出IP,int超时)
{
var pingTasks=ips.Select(ip=>
{
使用(Ping=new Ping())
{
返回ping.SendPingAsync(ip,超时);
}
});
var结果=等待任务.WhenAll(pingTasks);
返回结果。ToList();
}
关于问题可能是什么的任何提示?问题可能是您正在处理
ping
,而从SendPingAsync
返回的任务可能尚未完成。这将是一场激烈的比赛,这也许可以解释为什么你会看到这种不可预测的情况发生
在处理ping
之前,请尝试等待该任务:
public static async Task<List<PingReply>> PingAsync(List<IPAddress> ips, int timeout)
{
var pingTasks = ips.Select(async ip =>
{
using (Ping ping = new Ping())
{
return await ping.SendPingAsync(ip, timeout);
}
});
var results = await Task.WhenAll(pingTasks);
return results.ToList();
}
公共静态异步任务PingAsync(列出IP,int超时)
{
var pingTasks=ips.Select(异步ip=>
{
使用(Ping=new Ping())
{
返回wait ping.SendPingAsync(ip,超时);
}
});
var结果=等待任务.WhenAll(pingTasks);
返回结果。ToList();
}
请注意,在从SendPingAsync
返回的Task
完成之前,您已经处理了ping
,但无论如何,您没有使用ping
,因此您的第二个bug避免了第一个bug。。。可能这个问题是您没有处理(第二个)new Ping()
?我不确定它使用的是什么非托管资源。对不起,我只是看到我混合了两个版本的代码(我尝试了很多方法)。我将编辑问题以删除不必要的第二个Ping。但是如何在任务返回后正确处理Ping实例呢?在代码的编辑版本中,您可能在SendPingAsync
完成之前处理Ping
,从而导致不可预测的行为。只需将匿名函数传递给Select async-async ip=>。。。return wait ping.SendPingAsync
另请参见。在等待SendPingAsync
时,您正在失去并行性,不是吗?这就是的目的,当所有的第一个示例都无法编译,而第二个示例将失败,因为Ping
类不支持来自同一实例的并发Ping。@Phate01否。如果我在ips
上有一个循环,并且等待
在一个循环中,那么你是对的,但这是在创建一个异步函数(其中包含使用的和等待的),多次调用它,然后在一次调用中等待生成的任务go@Evk修复了丢失的返回值
。我不确定是否存在一致性,因此警告被删除。谢谢,这肯定是问题所在,因为现在它似乎总是工作正常。这也解释了我的奇怪行为,正如你提到的。