10

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){ }

}
csteinmueller
  • 2,427
  • 1
  • 21
  • 32
  • 1
    Do you have something on the main thread that prevent it from ending? Something like a while(true) ? – dcarneiro Apr 24 '12 at 14:09
  • Are you 100% sure that the RunWorkerCompleted is never called? Here is a SO question that proves this should work...http://stackoverflow.com/questions/1044460/unhandled-exceptions-in-backgroundworker – Justin Pihony Apr 24 '12 at 14:09
  • 1
    cant you debug and see what happens? what HandleException() returns? – Renatas M. Apr 24 '12 at 14:11
  • I don't have a while true or something like that. Just a Main(string[] args) and the static handler for the bw. And yes, the RunWorkerCompleted is never called. Neither the debugger stops there nor any operation at the start of the handler is executed (File.Create, Debug.WriteLine etc). – csteinmueller Apr 24 '12 at 14:15
  • @Reniuz - I'm sure I remember that the C# IDE has breakpoints! A red blob in the gutter on the first line of w_RunWorkerCompleted would be really useful. – Martin James Apr 24 '12 at 14:16
  • I cannot guess just by looking at the code. However i can advice you to add some trace statements inside the DoWork method (Also logging the thread Id's). Add a try-catch-finally block inside your DoWork method..just to confirm the exception is inside the DoWork thread. Also did you try just using a simple Thread rather than BackgroundWorker ? – this-Me Apr 24 '12 at 14:17
  • @csteinmueller - then put something in! A Sleep(10000) loop would do. – Martin James Apr 24 '12 at 14:17
  • HandleException is never called. The completed callback is never called. Just the DoWork handler is executed. – csteinmueller Apr 24 '12 at 14:18

1 Answers1

7

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.

Nick Butler
  • 24,045
  • 4
  • 49
  • 70
  • I've took a Console app, because it's the fastest way to test a library. It takes me much more time to present my results in a WPF application. – csteinmueller Apr 24 '12 at 14:25
  • 7
    @MartinJames I spend a significant portion of my time writing console apps that get scheduled and run on servers. A UI would be neither helpful nor feasible for such situations. It's also somewhat easier to do simple tests in a console app; less overhead involved just to do something simple and see the results. – Servy Apr 24 '12 at 14:28
  • 1
    OK! I take back the penguin stuff. Don't hit me any more :) – Martin James Apr 24 '12 at 15:16