关闭Windows窗体和取消后台工作程序的问题

时间:2014-03-06 15:10:26

标签: c# multithreading winforms backgroundworker

我正在使用后台工作程序来分析我的应用程序中弹出Windows窗体上的串行端口数据。作为我的应用程序防错的一部分,如果用户在操作期间尝试关闭表单,我希望能够停止/取消测试脚本。目前我的背景工作设置如下:

private void backgroundworker_DoWork(object sender, DoWorkEventArgs e)
{
    LogMsg(LogMsgType.Normal, "Test Started");
    // execute test script
}

如果我尝试关闭表单,我会得到一个“在创建窗口句柄之前无法在控件上调用Invoke或BeginInvoke”代码的LogMsg()部分异常:

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

考虑到这一点,我评估了StackOverflow上关于如何在关闭Windows窗体时取消线程的其他帖子。在这样做时,我遇到了一些代码,我已将其合并到我的应用程序中(见下文)。

volatile bool mClosePending = false;
volatile bool mCompleted = false;

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    mCompleted = true;
    if (mClosePending)
    {
        this.Close();
    }
}

protected override void OnFormClosing(FormClosingEventArgs e)
{
    if (!mCompleted)
    {
        backgroundWorker1.CancelAsync();
        this.Enabled = false;
        e.Cancel = true;
        mClosePending = true;
        return;
    }

    base.OnFormClosing(e);
}

即使在合并此代码后,我仍然会在代码的LogMsg()部分看到错误。任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:1)

即使在设置e.Cancel = true之后,也要执行base.OnFormClosing(e)。我认为这会奏效。

protected override void OnFormClosing(FormClosingEventArgs e)
{
e.Cancel = !mCompleted;
base.OnFormClosing(e)
    if (!mCompleted)
    {
        backgroundWorker1.CancelAsync();
        this.Enabled = false;
        mClosePending = true;

    }  

}

答案 1 :(得分:0)

你能把你的

base.OnFormClosing(e);

在方法的顶部?以防它覆盖你的

e.Cancel = true;

编辑,而不是使用volatile,为什么不使用

lock (this) {}

你什么时候开始背景工作者?可能在加载Form上的控件之前 - 这将解释错误消息...