在WPF UI线程中等待Dispatcher.Invoke

时间:2015-09-15 21:01:16

标签: c# wpf multithreading

我有一个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上等待?

2 个答案:

答案 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();
}