2

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?

Community
  • 1
  • 1
user626528
  • 13,999
  • 30
  • 78
  • 146

3 Answers3

4

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.

Igby Largeman
  • 16,495
  • 3
  • 60
  • 86
2

Why this can happen?

This can happen if you created the BackgroundWorker class inside a background thread.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • Darin is correct. The main purpose of it being run on the thread that created the BackgroundWorker is so if you create it off the main UI thread then you can interact with UI elements in the event without having cross thread problems since it will be executing on the main UI thread. – Parmenion Oct 19 '11 at 14:41
  • >RunWorkerCompleted is called not in the thread that created BackgroundWorker object<. Read question before writing your "answer" – user626528 Oct 20 '11 at 03:19
  • But the question is: is the thread it is created in a UI thread or already a background thread? It seems like it is called on the original thread if that is a UI thread. – riezebosch Oct 20 '11 at 09:23
  • 2
    No, even if you create BGW on a background thread, it will dispatch events to the UI thread. It's clever. – Igby Largeman Oct 24 '11 at 19:17
1

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.)

Mike Gledhill
  • 27,846
  • 7
  • 149
  • 159