BackgroundWorker.RunWorkerCompleted和threading

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专为GUI应用程序而设计。

我猜你是在控制台应用程序或除Winforms或WPF之外的其他类型的应用程序中这样做的。

BackgroundWorker使用SynchronizationContext.Current提供的同步模型来调度事件。 在GUI应用程序中,SynchronizationContext.Current使用WindowsFormsSynchronizationContext初始化,该窗口通过UI线程上的Invoking提供同步。

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

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

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

如果您在winforms应用程序中运行代码,它将按预期工作。

为什么会这样?

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

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

解决方案是在创建BackgroundWorker之前添加一行代码:

 SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext()); 

这里给出了解释:

Office解决方案中BackgroundWorker的行为不正确

如果不添加此行,则RunWorkerCompleted()函数将不会在原始UI线程下运行。

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