BackgroundWorker.RunWorkerCompleted和threading

时间:2011-10-19 14:24:02

标签: c# .net multithreading backgroundworker

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)
有什么想法吗?

3 个答案:

答案 0 :(得分:3)

BackgroundWorker专为GUI应用程序而设计。

我猜你是在控制台应用程序或除Winforms或WPF之外的其他类型的应用程序中执行此操作。

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

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

  

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

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

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

答案 1 :(得分:2)

  

为什么会发生这种情况?

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

答案 2 :(得分:1)

这是一个非常古老的主题..但是,如果在办公室地址中使用BackgroundWorker()时有其他人遇到此特定问题。

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

SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext());

这里给出了解释:

Incorrect behavior of BackgroundWorker in Office solutions

如果您不添加此行,那么您的RunWorkerCompleted()函数将不会在原始UI主题下运行。

(在我的情况下,这意味着我的RunWorkerCompleted()函数无法在我的Excel Addin项目中显示WPF对话框,并会抛出STA异常。)