BackgroundWorker.RunWorkerCompleted and threading

本文关键字:threading and RunWorkerCompleted BackgroundWorker | 更新日期: 2023-09-27 18:11:37

AFAIK,此事件承诺在创建者线程中调用(BackgroundWorker RunWorkerCompleted event);在大多数情况下,它都像承诺的那样。然而,有时RunWorkerCompleted在创建BackgroundWorker对象的线程中被称为而不是

更新:代码如下:

Trace.WriteLine(Thread.CurrentThread.ManagedThreadId);
var worker = new BackgroundWorker();
worker.DoWork += (s, args) => Trace.WriteLine(Thread.CurrentThread.ManagedThreadId);
worker.RunWorkerCompleted += (s, args) => Trace.WriteLine(Thread.CurrentThread.ManagedThreadId);
worker.RunWorkerAsync();

输出为1 7 7(正确输出必须为1 7 1)
什么好主意吗?

BackgroundWorker.RunWorkerCompleted and threading

BackgroundWorker是为GUI应用程序设计的。

我猜你是在控制台应用程序或其他类型的应用程序中做这个,而不是在Winforms或WPF中。

BackgroundWorker使用SynchronizationContext提供的同步模型。当前到分派事件。在GUI应用程序中,SynchronizationContext。Current是用WindowsFormsSynchronizationContext初始化的,它通过在UI线程上调用提供同步。

但是在非gui应用程序中,SyncronizationContext。Current只是一个SynchronizationContext对象,它(来自MSDN):

是一个基类,它提供一个没有同步的自由线程上下文。

换句话说,它只是通过线程池调度,所以每次你通常会得到一个不同的线程。

如果你在winforms应用程序中运行你的代码,它会像预期的那样工作。

为什么会发生这种情况?

如果你在后台线程中创建BackgroundWorker类,就会发生这种情况。

这是一个非常老的线程。但以防其他人在Office插件中使用BackgroundWorker()时遇到这个特定问题。

解决方案是在创建BackgroundWorker之前添加一行代码:
SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext());

解释如下:

Office解决方案中BackgroundWorker的错误行为

如果你不添加这一行,那么你的RunWorkerCompleted()函数将不会在原来的UI线程下运行。

(在我的例子中,这意味着我的RunWorkerCompleted()函数无法在我的Excel插件的项目中显示WPF对话框,并且会抛出STA异常。)