我正在使用后台工作程序来分析我的应用程序中弹出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()
部分看到错误。任何帮助将不胜感激。
答案 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
上的控件之前 - 这将解释错误消息...