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是为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异常。)