BackgroundWorker exception handling

csteinmueller picture csteinmueller · Apr 24, 2012 · Viewed 16.3k times · Source

I'm working with the following components:

  • a Library (which throws an exception)
  • a test-console to test my logging
  • the enterprise library exception handling application blocks
  • the enterprise library logging application blocks

I'm invoking the library method by using a backgroundworker. The library throws the exception but the RunWorkerCompleted handler is never called.

The only way to catch the exception is to surround my DoWork handler code with a try/catch block.

Did is misunderstand the RunWorkerCompletedEventArgs.Error Property? Isn't it for getting exceptions which got caught by the BackgroundWorker?

Codesample:

static BackgroundWorker w = new BackgroundWorker();

w.DoWork += new DoWorkEventHandler(w_DoWork);
w.RunWorkerCompleted += 
   new RunWorkerCompletedEventHandler(w_RunWorkerCompleted);
w.RunWorkerAsync();



static void w_DoWork(object sender, DoWorkEventArgs e)
{
   MyClass m  = new MyClass();
   w.result = m.Compute();
}

static void w_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
   if (e.Error != null)
   {
      HandleException(e.Error);
   }

   /* result related code */

}


static void HandleException(Exception e)
{
   ExceptionPolicy.HandleException(e, "MyPolicy");
}

The above sample leads to a termination of my console application. The vs2010 output writes absolutely nothing (only default output).

So where's the problem?

//Edit: this snippet works for catching the library's exception.

static void w_DoWork(object sender, DoWorkEventArgs e)
{
   try
   {
      MyClass m  = new MyClass();
      w.result = m.Compute();
   }catch(Exception e){ }

}

Answer

Nicholas Butler picture Nicholas Butler · Apr 24, 2012

That is the correct pattern for BackgroundWorker.

I suspect the problem is that your Main method is exiting before the BW has completed.

RunWorkerAsync will return immediately and if you are not waiting in Main, then your process will end, perhaps even before the BW has started, never mind completed.

Try adding a Console.ReadLine at the end of your Main method.


Out of interest:

BW behaves differently in a Console app and a Windows app. If you use a WinForms or WPF app, there will be a derived SynchronizationContext on your UI thread and BW will marshal RunWorkerCompleted back to the UI thread and run it there. That's one of the main benefits of BW.

In a Console App, the default SynchronizationContext is used and this marshals RunWorkerCompleted onto a thread pool thread. This means you can block the Main thread and the completed handler will still run.