我有一个应用程序,我在其中启动一个窗口,显示来自第三方工具的字节数据。我已将.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();
}));
}
答案 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;
}
}
}
希望这有帮助。