问题
AFAIK, this event is promised to be called in the creator thread (BackgroundWorker RunWorkerCompleted Event); and in the most cases, it does as promised. However, sometimes RunWorkerCompleted is called not in the thread that created BackgroundWorker object.
Update: Code is like this:
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();
Output is 1 7 7 (correct output must be 1 7 1)
Any ideas?
回答1:
BackgroundWorker is designed for GUI applications.
I'm guessing you're doing this in a console application or some other type of application other than Winforms or WPF.
BackgroundWorker uses the synchronization model provided by SynchronizationContext.Current to dispatch events. In a GUI application, SynchronizationContext.Current is initialized with a WindowsFormsSynchronizationContext
, which provides synchronization by Invoking on the UI thread.
But in a non-GUI application, SyncronizationContext.Current is just a SynchronizationContext
object, which (from MSDN):
is a base class that provides a free-threaded context with no synchronization.
In other words it simply dispatches via the threadpool, so you'll usually get a different thread each time.
If you run your code in a winforms application, it will work as expected.
回答2:
Why this can happen?
This can happen if you created the BackgroundWorker class inside a background thread.
回答3:
This is a really old thread.. but just in case anyone else hits this specific issue when using BackgroundWorker()
in an Office Addin.
The solution is to add one line of code before creating your BackgroundWorker
:
SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext());
The explanation is given here:
Incorrect behavior of BackgroundWorker in Office solutions
If you don't add this line, then your RunWorkerCompleted()
function will not run under the original UI thread.
(In my case, this meant that my RunWorkerCompleted()
function could not display the WPF dialogs in my Excel Addin's project, and would throw an STA exception.)
来源:https://stackoverflow.com/questions/7822784/backgroundworker-runworkercompleted-and-threading