C# c等待最后一个要触发的事件

C# c等待最后一个要触发的事件,c#,events,wait,C#,Events,Wait,我尝试实现一种功能,以获得服务器列表中最快的服务器。 因此,我需要等待,直到所有ping都通过异步方法得到处理 private List<Container.Server> serverList = new List<Container.Server>(); private Container.Server fastestServer; private IPAddress GetFastestServer(List<string> ad

我尝试实现一种功能,以获得服务器列表中最快的服务器。 因此,我需要等待,直到所有ping都通过异步方法得到处理

    private List<Container.Server> serverList = new List<Container.Server>();
    private Container.Server fastestServer;
    private IPAddress GetFastestServer(List<string> addresses)
    {
        foreach (string address in addresses)
        {
            Ping ping = new Ping();
            ping.PingCompleted += ping_PingCompleted;
            ping.SendAsync(ResolveDomainName(address), null);
        }
        return fastestServer.Address;
    }
    void ping_PingCompleted(object sender, PingCompletedEventArgs e)
    {
        serverList.Add(new Container.Server(e.Reply.Address, e.Reply.RoundtripTime));
        fastestServer = serverList.OrderBy(o => o.Latency).FirstOrDefault();
    }
处理完addressList中的所有地址后,该方法立即返回最快的地址,但不能保证所有ping都已部署

也许你可以告诉我,在处理return命令之前,是否可以等待所有sendaync完成


我知道使用synchron Send方法会更容易,但我想知道是否有一种解决方法可以解决它:

我会放弃基于事件的方法,转而使用async/Wait。现在您可以:

async Task<IEnumerable<PingReply>> GetPingReplies(IEnumerable<string> hosts)
{
    var tasks = hosts.Select(host => new Ping().SendPingAsync(host)).ToArray();
    await Task.WhenAll(tasks);
    return tasks.Select(task=>task.Result);

}
所以现在你可以从其他地方:

async Task<string> GetFastest(IEnumerable<string> hostList)
{
    var replies = await GetPingReplies(hostList);
    var hostsAndReplies = 
         hostList.Zip(replies, (host, reply) => new{host,reply});
    var fastest=
         hostsAndReplies
          .Where(x => x.reply.Status == IPStatus.Success)
          .OrderBy(x => x.reply.RoundtripTime)
          .FirstOrDefault();
    return fastest == null ? null : fastest.host;
}

我不清楚,如果你只对最快的回复感兴趣,那么除了第一次成功回复之外,你为什么还想留下来做任何事情。

有很多方法可以做到这一点。SendAsync返回什么?您可以将其简化为返回任务。WhenAllhosts.Selecthost=>new Ping.SendPingAsynchost;甚至不需要使用async/await。@Servy:Neato!为了清晰起见,我留下了扩展版,但是是的,你是对的。虽然一行程序没有风险,但我倾向于通过调用.ToArray来确保生成热任务的查询立即具体化,因此没有重复枚举的风险。即使WhenAll在内部没有这样做,代码也不会重复序列两次。即使您希望将ToArray保留在那里,它也是多余的,因为它在内部将其转换为数组,但额外的Select,尤其是wait,会给解决方案增加一些实际的开销和复杂性。