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)
有什么想法吗?
答案 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异常。)