我有一个BackgroundWorker
偶尔需要调用UI线程来执行一些工作并检索结果。为了实现这一点,我在后台线程中使用以下内容:
App.Current.Dispatcher.Invoke(new Action(() => { /* some code that updates local data */ });
当应用程序退出时,我希望能够告诉BackgroundWorker
退出,但我想允许它完成当前的任何操作。换句话说,我想调用BackgroundWorkerObj.CancelAsync()
然后提取消息,直到线程退出。
我尝试了以下内容,但后台线程中的Invoke()
仍然阻塞(尽管UI线程仍在搅拌):
Worker.CancelAsync();
while (Worker.IsBusy)
{
DispatcherFrame Frame = new DispatcherFrame();
Frame.Continue = false;
Dispatcher.PushFrame(Frame);
}
这样做的正确方法是什么?在仍然从BackgroundWorker
对象执行Invokes时,UI线程如何在BackgroundWorker
上等待?
答案 0 :(得分:1)
这种关闭死锁正是为什么你不应该为此目的使用Invoke的原因。
将其更改为BeginInvoke(),并且要返回工作线程,请使用事件。
答案 1 :(得分:0)
我会使用Task.Run,因为您使用的是.NET 4.0。但无论如何。你必须以相反的方式做到这一点。等待backgroundworker完成然后退出应用程序。在保持主线程响应的同时,无法等待后台线程在关闭事件中完成。这个while循环将阻塞主线程和消息泵,直到后台线程完成。
试试这个
私人BackgroundWorker _worker;
protected override OnFormClosing( object sender , FormClosingEventArgs e )
{
base.OnFormClosing( sender , e );
// Cancel's the closing and keeps the form alive
e.Cancel = _worker.IsBusy;
}
private void RunWorkerCompleted( object sender , RunWorkerCompletedEventArgs e)
{
// Work is done, so close the form
Close();
}