如何在 Form 的 Closing 事件上停止 BackgroundWorker? [英] How to stop BackgroundWorker on Form's Closing event?
问题描述
我有一个生成 BackgroundWorker 的表单,它应该更新表单自己的文本框(在主线程上),因此 Invoke((Action) (...));
调用.
如果在 HandleClosingEvent
我只做 bgWorker.CancelAsync()
然后我在 Invoke(...)
上得到 ObjectDisposedException
打电话,可以理解.但是,如果我坐在 HandleClosingEvent
中等待 bgWorker 完成,那么 .Invoke(...) 永远不会返回,这也是可以理解的.
I have a form that spawns a BackgroundWorker, that should update form's own textbox (on main thread), hence Invoke((Action) (...));
call.
If in HandleClosingEvent
I just do bgWorker.CancelAsync()
then I get ObjectDisposedException
on Invoke(...)
call, understandably. But if I sit in HandleClosingEvent
and wait for bgWorker to be done, than .Invoke(...) never returns, also understandably.
任何想法如何关闭此应用程序而不会出现异常或死锁?
Any ideas how do I close this app without getting the exception, or the deadlock?
以下是简单 Form1 类的 3 个相关方法:
Following are 3 relevant methods of the simple Form1 class:
public Form1() {
InitializeComponent();
Closing += HandleClosingEvent;
this.bgWorker.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) {
while (!this.bgWorker.CancellationPending) {
Invoke((Action) (() => { this.textBox1.Text = Environment.TickCount.ToString(); }));
}
}
private void HandleClosingEvent(object sender, CancelEventArgs e) {
this.bgWorker.CancelAsync();
/////// while (this.bgWorker.CancellationPending) {} // deadlock
}
推荐答案
据我所知,唯一的死锁安全和异常安全的方法是实际取消 FormClosing 事件.如果 BGW 仍在运行,则设置 e.Cancel = true 并设置一个标志以指示用户请求关闭.然后在 BGW 的 RunWorkerCompleted 事件处理程序中检查该标志,如果已设置,则调用 Close().
The only deadlock-safe and exception-safe way to do this that I know is to actually cancel the FormClosing event. Set e.Cancel = true if the BGW is still running and set a flag to indicate that the user requested a close. Then check that flag in the BGW's RunWorkerCompleted event handler and call Close() if it is set.
private bool closePending;
protected override void OnFormClosing(FormClosingEventArgs e) {
if (backgroundWorker1.IsBusy) {
closePending = true;
backgroundWorker1.CancelAsync();
e.Cancel = true;
this.Enabled = false; // or this.Hide()
return;
}
base.OnFormClosing(e);
}
void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
if (closePending) this.Close();
closePending = false;
// etc...
}
这篇关于如何在 Form 的 Closing 事件上停止 BackgroundWorker?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!