C# 如何在 BackGroundWorker 中停止 Ping / 在函数之外停止发送异步

本文关键字:异步 函数 BackGroundWorker Ping | 更新日期: 2023-09-27 18:30:27

所以我有一个看起来像这样的BW:

    private void bw_DoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker worker = sender as BackgroundWorker;
        if ((worker.CancellationPending == true))
        {
            e.Cancel = true;
            return;
        }
        else
        {
            worker.ReportProgress(1);
            e.Result = PCIsOnline((string)e.Argument);
        }
    }

PCIsOnline 功能启动 Ping.Send。一切正常。但在某些情况下,我想停止 BW(或停止 ping)。

我试过这个:

BW。取消异步();- 但这对我没有帮助,因为APP永远不会再回到bw_DoWork停止。所以我有一种方法可以停止ping或bw。所以我可以重新开始。

顺便说一句,出于某种原因,这也无济于事。

    bw.CancelAsync();
    while (!bw.IsBusy)
    {
        System.Threading.Thread.Sleep(50);
    }

因为它只是永远循环。我想这是因为我睡眠线程,但它是一个主线程,尽管 BW 线程不应该停止。但似乎确实如此。我见过一个线程,其中使用了睡眠 DoEvents 而不是睡眠,但我使用的是 WPF 并且它没有它。而且我真的不想等待ping来完成它的工作。

我已经阅读了很多关于 BW 以及如何停止的帖子,但没有一个对我有帮助。Coz 当我发送 CancelAsync() DoWork 时,一切都准备好了取消待处理检查,永远不会回到那里。

PS:第一次时间我开始 BW 甚至TextBox_FocusLost。并希望在List_SelectChanged中再次停止并运行它。

添加:

public static bool PCIsOnline(string arg)
{
    Ping pingSender = new Ping();
    PingOptions options = new PingOptions();
    options.DontFragment = true;
    string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
    byte[] buffer = Encoding.ASCII.GetBytes(data);
    int timeout = 2;
    try
    {
        PingReply reply = pingSender.Send(arg, timeout, buffer, options);
        if (reply.Status == IPStatus.Success) { return true; }
        else { return false; }
    }
    catch
    {
        return false;
    }
}

新增2:正如之前在评论中所说,与其使用 BW,不如使用 SendAsync。我的代码现在看起来像这样。但我仍然不明白如何在PCIsOnline功能之外停止SendAsync。

public static void PCIsOnline(string arg)
{
    Ping pingSender = new Ping();
    pingSender.PingCompleted += new PingCompletedEventHandler(PingCompletedCallback);
    PingOptions options = new PingOptions();
    options.DontFragment = true;
    string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
    byte[] buffer = Encoding.ASCII.GetBytes(data);
    int timeout = 2;
    pingSender.SendAsync(arg, timeout, buffer, options);
}
private static void PingCompletedCallback(object sender, PingCompletedEventArgs e)
{
    if (e.Cancelled)
    {
        Console.WriteLine("Ping canceled.");
    }
    if (e.Error != null)
    {
        Console.WriteLine("Ping failed:");
        Console.WriteLine(e.Error.ToString());
    }
    PingReply reply = e.Reply;
    HandleReply(reply);
}

所以我仍然在寻找一种方法来中断 BW 并重新启动它或停止 PingAsync。

C# 如何在 BackGroundWorker 中停止 Ping / 在函数之外停止发送异步

问题是你只向 bw 发送取消。但是您还需要向Ping(SendAsync)发送取消。

发送取消到平

Ping.SendAsyncCancel();
bw.CancelAsync();

使用发送异步:

public static bool PCIsOnline(string arg)
{
Ping pingSender = new Ping();
PingOptions options = new PingOptions();
options.DontFragment = true;
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
int timeout = 2;
try
{
    PingReply reply = pingSender.SendAsync(arg, timeout, buffer, options);
    if (reply.Status == IPStatus.Success) { return true; }
    else { return false; }
}
catch
{
    return false;
}
}

由于我找不到停止ping的方法,因此如果不是我需要的ATM结果,我决定忽略ping结果。所以我只是将签入添加到 HandleReply 中,如果不再需要此 ping 结果,则发送返回

private void Name_LostFocus(object sender, System.EventArgs e)
{
    var textBox = sender as TextBox;
    //No longer Using BW since Ping.SendAsync() does the job
    PCIsOnline(textBox.Text); 
}
private void Search_SelectChanged(object sender, SelectionChangedEventArgs e)
{
    ListBox Search = sender as ListBox;
    if (Search.SelectedValue != null)
    {
        this.OldName.Text = Search.SelectedValue.ToString();
        PCIsOnline(this.OldName.Text);
    }
}
public void PCIsOnline(string arg)
{
    Ping pingSender = new Ping();
    //Sending argument to perform check later
    pingSender.PingCompleted += (sender1, args) => PingCompletedCallback(sender1, args, arg);
    PingOptions options = new PingOptions();
    options.DontFragment = true;
    string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
    byte[] buffer = Encoding.ASCII.GetBytes(data);
    int timeout = 5;
    pbrTest.Visibility = System.Windows.Visibility.Visible;
    pingSender.SendAsync(arg, timeout, buffer, options);
}
private void PingCompletedCallback(object sender, PingCompletedEventArgs e, String Current)
{
    if (e.Cancelled)
    {
        HandleReply(null, Current, "Cancelled");
        return;
    }
    if (e.Error != null)
    {
        HandleReply(null, Current, "Error");
        return;
    }
    PingReply reply = e.Reply;
    HandleReply(reply, Current, "");
}
private void HandleReply(PingReply reply, String PC, String msgtype = "")
{
    //Ignore old result I only need one that is in OldName textBox
    if (PC != this.OldName.Text) { return; }
    //Next you should add your result handling
    //Happens on a error
    if (reply == null)
    {
        /*do something*/
    }
    //PC is online
    else if (reply.Status == IPStatus.Success)
    {
        /*do something*/
    }
    //PC is offline
    else
    {
        /*do something*/
    }
}

不是解决问题的最好方法,但这是我能想到的最好的方法。