Unhandled exceptions in BackgroundWorker
What you're describing is not the defined behavior of BackgroundWorker. You're doing something wrong, I suspect.
Here's a little sample that proves BackgroundWorker eats exceptions in DoWork, and makes them available to you in RunWorkerCompleted:
var worker = new BackgroundWorker();
worker.DoWork += (sender, e) =>
{
throw new InvalidOperationException("oh shiznit!");
};
worker.RunWorkerCompleted += (sender, e) =>
{
if(e.Error != null)
{
MessageBox.Show("There was an error! " + e.Error.ToString());
}
};
worker.RunWorkerAsync();
My psychic debugging skills are revealing your problem to me: You are accessing e.Result in your RunWorkerCompleted handler -- if there's an e.Error, you must handle it without accessing e.Result. For example, the following code is bad, bad, bad, and will throw an exception at runtime:
var worker = new BackgroundWorker();
worker.DoWork += (sender, e) =>
{
throw new InvalidOperationException("oh shiznit!");
};
worker.RunWorkerCompleted += (sender, e) =>
{
// OH NOOOOOOOES! Runtime exception, you can't access e.Result if there's an
// error. You can check for errors using e.Error.
var result = e.Result;
};
worker.RunWorkerAsync();
Here's a proper implementation of the RunWorkerCompleted event handler:
private void RunWorkerCompletedHandler(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error == null)
{
DoSomethingWith(e.Result); // Access e.Result only if no error occurred.
}
}
VOILA, you won't receive runtime exceptions.
Unhandled exceptions in BackgroundWorker
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
Background worker exception handling
I suggest you to create some business specific exception, which describes operation which you were doing in background. And throw this exception with original exception as inner exception:
private void bgWorker_RunWorkerCompleted(
object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
throw new BusinessSpecificException("Operation failed", e.Error);
// ...
}
Thus original exception with its stack trace will be available, and you'll have more descriptive exception thrown.
Note - if you don't want to create new exception class, you can use existing ApplicationException or Exception. But its not that informative and if you are going to catch it somewhere, then you'll not be able to catch this particular exception only
BackgroundWorker exception handling
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.
Unhandled exceptions and background workers
The other threads will carry on. Only the thread used by the BackgroundWorker
will crash.
An unhandled exception will be thrown. Since there is no exception handling in the event handler, it will get caught by the CLR as a last resort. This will not influence other threads.
Related Topics
Watermark in System.Windows.Forms.Textbox
Can You Specify Format for Xmlserialization of a Datetime
Datagrid Get Selected Rows' Column Values
Is SQLcommand.Dispose() Required If Associated SQLconnection Will Be Disposed
How to Interrupt Console.Readline
How to Create a Custom Messagebox
How to (De)Construct Data Frames in Websockets Hybi 08+
How to Test If a Type Is Anonymous
How to Delete a Registry Value in C#
System.Data.Sqlclient.Sqlexception: Login Failed for User
Delegate Caching Behavior Changes in Roslyn
Why Is Only the UI Thread Allowed to Modify the Ui
How to Conditionally Compile My C# for Mono VS. Microsoft .Net