运行时取消BackgroundWorker

时间:2014-06-03 17:52:20

标签: c# backgroundworker

我有一个应用程序,我在其中启动一个窗口,显示来自第三方工具的字节数据。我已将.CancelAsync().CancellationPending添加到我的代码中(见下文),但我还遇到了另一个问题。

private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
    Thread popupwindow = new Thread(() => test());
    popupwindow.Start(); // start test script

    if(backgroundWorker.CancellationPending == true)
    {
       e.Cancel = true;
    }
}

private voide window_FormClosing(object sender, FormClosingEventArgs e)
{
   try
   {
      this.backgroundWorker.CancelAsync();
   }
   catch (Exception ex)
   {
      MessageBox.Show(ex.Message.ToString());
   }
}

取消测试后,我的弹出窗口中的富文本框出现“发生InvalidOperationException”错误。它声明在创建窗口句柄之前,无法在控件上调用“Invoke或BeginInvoke”。我不完全确定这意味着什么,并感谢你的帮助。

Rich Text Box的LogWindow代码:

public void LogWindowText(LogMsgType msgtype, string msgIn)
    {
        rtbSerialNumberValue.Invoke(new EventHandler(delegate
        {
            rtbWindow.SelectedText = string.Empty;
            rtbWindow.SelectionFont = new Font(rtbWindow.SelectionFont, FontStyle.Bold);
            rtbWindow.SelectionColor = LogMsgTypeColor[(int)msgtype];
            rtbWindow.AppendText(msgIn);
            rtbWindow.ScrollToCaret();
        }));
    }

2 个答案:

答案 0 :(得分:0)

在后台工作程序的finalize方法(LogWindowText处理程序)调用RunWorkerCompleted方法之前,窗口句柄已经消失了。您需要检查Handle

if (this.Handle == IntPtr.Zero) { return; }

答案 1 :(得分:0)

阅读完代码后;看来背景工作者几乎立即完成;可能会杀死从中生成的任何线程。更重要的是;已经停止的后台工作程序将抛出" InvalidOperationException"当" CancelAsync"被称为。

我建议将任何与GUI相关的工作放入调用者而不是后台工作者线程。这是一个重要的考虑因素,因为您将获得跨线程异常和其他奇怪的行为,例如相当严重的GUI刷新问题。

后台工作人员" DoWork"方法应该被认为是线程的。您可以通过向代码添加简单的调试语句来看到这一点。

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);

        backgroundWorker1.RunWorkerAsync();
    }

最后;我补充说,在循环结构中轮询时,CancellationPending的效果最好,

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        foreach (var workItem in work)
        {
            workItem.Perform();

            if (backgroundWorker1.CancellationPending)
            {
                break;
            }
        }
    }

希望这有帮助。