Why WhenAll waits indefinetely with multiple pings?

Viewed 196

My application needs to ping all possible IP addresses in a network. Since the IP list is big (about 4000 entries) I decided to do the ping asynchronously to speed up the process. The code I wrote initially seemed to work fine, but somehow when I tried it yesterday it didn't work as expected anymore (maybe after some .NET updates? I don't really know).

Here is how my code works: from the list of IP addresses I created a list of tasks (one for each IP) and then passed the list of tasks to WhenAll to wait for all ping requests to finish. The problem is that sometimes WhenAll waits indefinitely (I checked it with the debugger and I saw that some of the tasks passed to WhenAll always remained in the State "Waiting for activation"). The strange thing is that sometimes (about 2 times in 3 tests) it works as expected and all tasks completes.

Here is the code I used:

    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();
     }

Any hint on what the problem could be?

1 Answers

The issue is potentially that you're disposing ping before the Task returned from SendPingAsync might have completed. This will be racey, which might explain why you're seeing this happen unpredictably.

Try awaiting that Task before disposing 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();
}
Related