Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unhandled exceptions in BackgroundWorker

My WinForms app uses a number of BackgroundWorker objects to retrieve information from a database. I'm using BackgroundWorker because it allows the UI to remain unblocked during long-running database queries and it simplifies the threading model for me.

I'm getting occasional DatabaseExceptions in some of these background threads, and I have witnessed at least one of these exceptions in a worker thread while debugging. I'm fairly confident these exceptions are timeouts which I suppose its reasonable to expect from time to time.

My question is about what happens when an unhandled exception occurs in one of these background worker threads.

I don't think I can catch an exception in another thread, but can I expect my WorkerCompleted method to be executed? Is there any property or method of the BackgroundWorker I can interrogate for exceptions?

like image 423
Ed Guiness Avatar asked Nov 03 '08 13:11

Ed Guiness


2 Answers

If the operation raises an exception that your code does not handle, the BackgroundWorker catches the exception and passes it into the RunWorkerCompleted event handler, where it is exposed as the Error property of System.ComponentModel.RunWorkerCompletedEventArgs. If you are running under the Visual Studio debugger, the debugger will break at the point in the DoWork event handler where the unhandled exception was raised.

http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.dowork.aspx

like image 79
Ed Guiness Avatar answered Sep 28 '22 06:09

Ed Guiness


I am fully using BackgroundWorker over a years and really know it in deep.

Just recently, My RunWorkerCompleted does not catch the e.Error when I simply Throw New Exception("Test") in DoWork. However Unhandled Exception raised. Catch in DoWork is not the best practice thus e.Error got no meaning.

When I try to create new Form with new BackgroundWorker, e.Error in RunWorkerCompleted handled successfully. There should be something wrong in my complicated BackgroundWorker.

After a few days googling and debugging, trying an error. I found this in my RunWorkerCompleted:

  • Check for e.Error first, then e.Cancelled and lastly e.Result
  • Do not get the e.Result if e.Cancelled = True.
  • Do not get the e.Result if e.Error is not null (or Nothing) **

** This is where I miss. If you trying to use e.Result if e.Error is not null (or Nothing), Unhandled Exception will thrown.


UPDATE: In the e.Result get property .NET design it to check for e.Error first, if got error, then they will re-throw the same exception from DoWork. That is why we get Unhandled exception in RunWorkerCompleted but actually the exception is come from DoWork.

Here is the best practice to do in RunWorkerCompleted:

If e.Error IsNot Nothing Then   ' Handle the error here Else   If e.Cancelled Then     ' Tell user the process canceled here   Else     ' Tell user the process completed     ' and you can use e.Result only here.   End If End If 

If you want an object that accessible to all DoWork, ProgressChanged and RunWorkerCompleted, use like this:

Dim ThreadInfos as Dictionary(Of BackgroundWorker, YourObjectOrStruct) 

You can easily access ThreadInfos(sender).Field anywhere you want.

like image 29
CallMeLaNN Avatar answered Sep 28 '22 07:09

CallMeLaNN