C#如何在BackGroundWorker中停止Ping /在函数外停止SendAsync

时间:2014-11-15 11:55:59

标签: c#

所以我的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.CancelAsync(); - 但这并没有帮助我因为APP将永远不会再回到bw_DoWork停止。所以我有办法停止ping或bw。 所以我可以重新开始。

顺便说一下,这也没有帮助。

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

永远满足它的正常循环。我猜它是becoz我睡眠线程,但它是一个主线程我虽然BW线程不应该停止。但它似乎确实如此。我已经看到一个线程,而不是睡眠DoEvents被使用,但我使用WPF,它没有它。而且我真的不想等待ping来完成它的工作。

我已经阅读了很多关于BW的线索以及如何停止但在我的情况下没有一个是有帮助的。当我发送CancelAsync()时,DoWork已经通过了CancellationPending检查并且永远不会返回。

PS:Fisrt time我在TextBox_FocusLost中启动BW甚至。并希望在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;
    }
}

ADDED2: 正如之前在评论中所述,而不是使用BW更好地使用SendAsync。 Аnd我的代码现在看起来像这样。但我仍然不明白如何在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的方法。

2 个答案:

答案 0 :(得分:0)

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

向Ping发送取消

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

使用SendAsync:

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

答案 1 :(得分:0)

由于我找不到停止ping的方法,我决定忽略ping结果,如果它不是我需要ATM的那个。 所以我只是将签入添加到 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*/
    }
}

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