停止 Ping.发送异步按钮单击“WPF”



美好的一天。请帮帮我如何在这里停止 SendPingAsync 方法,我尝试了 SendAsyncCancel,但它只停止一个线程,我需要取消所有 pong 线程。

private void refreshbtn_Click(object sender, EventArgs e)
    {
        if (tokenSource != null) //check if its even initialized or not
            tokenSource.Cancel();
        lstNetworks.Items.Clear();
        string gate_ip = NetworkGateway();
        //Extracting and pinging all other ip's.
        string[] array = gate_ip.Split('.');
        for (int i = 1; i <= 255; i++)
        {
            string ping_var = array[0] + "." + array[1] + "." + array[2] + "." + i;
            //time in milliseconds           
            Ping(ping_var, 1, 4000);
        }
    }
    public void Ping(string host, int attempts, int timeout)
    {
        tokenSource = new CancellationTokenSource();
        Task.Factory.StartNew(() =>
        {
            try
                {
                    System.Net.NetworkInformation.Ping ping = new System.Net.NetworkInformation.Ping();
                    ping.PingCompleted += new PingCompletedEventHandler(PingCompletedCallback);
                    ping.SendAsync(host, timeout, host);
                }
                catch
                {
                    // Do nothing and let it try again until the attempts are exausted.
                    // Exceptions are thrown for normal ping failurs like address lookup
                    // failed.  For this reason we are supressing errors.
                }
        }, tokenSource.Token);
    }
    private void PingCompletedCallback(object sender, PingCompletedEventArgs e)
    {
        // If an error occurred, display the exception to the user. 
        if (e.Reply.Status == IPStatus.Success)
        {
            string hostName = GetHostName(e.Reply.Address.ToString());
            string macAdress = GetMacAddress(e.Reply.Address.ToString());
            if (!Dispatcher.CheckAccess())
            {
                Dispatcher.Invoke(new Action(() =>
                {
                        lstNetworks.Items.Add(new InfoItem() { IP = e.Reply.Address.ToString(), MAC = macAdress, HOST = hostName });
                    lstNetworks.Items.SortDescriptions.Add(new SortDescription("IP", ListSortDirection.Ascending));
                }));
            }
        }
        else {
            //Console.WriteLine(String.Concat("Non-active IP: ", e.Reply.Address.ToString()))
        }
    }

每次我单击刷新按钮时,我都应该开始新的ping操作。就我而言,只停止一个ping线程,但其余的继续工作。

更新

我尝试像你写的那样,当我再次按下刷新按钮时,我的应用程序冻结,直到所有线程停止(30 秒)。但是当应用程序解冻时,结果相同,我之前发送异步的所有ping数据包都会添加我第二次发送的新SensAsync数据包。我不仅需要停止线程,还需要停止 SendAsync 线程。有一个方法SendAsyncCancel,但是当取消令牌触发时,我如何在同时调用它。

您每次都会创建TokenSource的不同实例。相反,只创建一个,将相同的实例传递到所有Tasks。然后,每个Task都会检查Token是否有取消请求,然后您可以对每个请求进行 WaitAll,并将Token传递到其中。

private async void refreshbtn_Click(object sender, EventArgs e)
{
    if (tokenSource != null) //check if its even initialized or not
        tokenSource.Cancel();
    lstNetworks.Items.Clear();
    string gate_ip = NetworkGateway();
    //Extracting and pinging all other ip's.
    tokenSource = new CancellationTokenSource();
    string[] array = gate_ip.Split('.');
    List<Task> tasks = new List<Task>();
    for (int i = 1; i <= 255; i++)
    {
        string ping_var = array[0] + "." + array[1] + "." + array[2] + "." + i;
        var task = Task.Factory.StartNew(() =>
        {
            if (tokenSource.Token.IsCancellationRequested) return;
            //time in milliseconds           
            Ping(ping_var, 1, 4000, tokenSource.Token);
        }, tokenSource.Token);
        tasks.Add(task);
    }
    await Task.WhenAll(tasks.ToArray());
}
public void Ping(string host, int attempts, int timeout, CancellationToken cancellationToken)
{
    try
    {
        System.Net.NetworkInformation.Ping ping = new System.Net.NetworkInformation.Ping();
        cancellationToken.Register(() => ping.SendAsyncCancel());
        ping.PingCompleted += new PingCompletedEventHandler(PingCompletedCallback);
        ping.SendAsync(host, timeout, host);
    }
    catch
    {
        // Do nothing and let it try again until the attempts are exausted.
        // Exceptions are thrown for normal ping failurs like address lookup
        // failed.  For this reason we are supressing errors.
    }
}

更新:

添加了异步/等待,因此它不会阻止 UI。每个 Ping 的注册取消令牌,以便它可以自行取消。

最新更新