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

时间:2014-02-27 19:31:43

标签: c# multithreading ping

我似乎无法理解如何构建对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文档和大量问题,我只是没有得到它。

5 个答案:

答案 0 :(得分:13)

你想做的事情如下:

private async Task<List<PingReply>> 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进行调用后将范围添加到集合中代码更清晰,更容易出错。

答案 1 :(得分:2)

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

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

await Task.WhenAll(your all ping requests)

答案 2 :(得分:1)

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

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

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

var pingResults = await Task.WhenAll(pingTasks);

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

答案 3 :(得分:0)

我是这样做的

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

在BackgroundWorker中我这样做

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

答案 4 :(得分:0)

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