BackgroundWorker & Exceptions - c#

The MSDN Docs says
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
But when I tried
_workers[i].DoWork += (s, args) =>
{
throw new Exception("Error!");
};
I get Exception Unhandled error ... The code doesn't seem to go to RunWorkerCompleted. How are errors supposed to be handled?
UPDATE
I have setup simple handlers
_workers[i].DoWork += (s, args) =>
{
throw new Exception("Error!");
}
...
_workers[i].RunWorkerCompleted += (s, args) =>
{
if (args.Error != null) {
string dummy = args.Error.Message;
}
...
};
The code never leaves DoWork

If an exception is thrown and passes through user frames but is then not caught by user code, it is considered "user-unhandled".
So I think there are 3 possibilities:
This is a first-chance exception - so if you press F5, the exception will propagate as normal.
Click "edit code" in the Exception Assistant. Then do some Edit and Continue to solve the problem.
Go to Debug->Exceptions and de-select the "user-unhandled" column.

If you are running through the debugger, Visual Studio will stop on exceptions in the BackgroundWorker.DoWork event handler rather than silently passing the exception to the RunWorkerCompleted event which is what happens when not in the debugger.
1) You can just hit F5 and continue execution to follow the exception (as RoadWarrior mentioned)
2) If that is too annoying, for DoWork don't use delegates/lambdas but use named methods and decorate with [DebuggerStepThrough] Attribute. This will let the debugger ignore that method and not stop on exception so you can view the "normal" behavior of the Backgroundworker.
See: Visual Studio 2008 Debugging - Skipping code

I've done exception handling in BackgroundWorker yesterday. I didn't add any throw in Worker's DoWork handler. If exception happens, you will be able to get it in RunWorkerCompleted without throwing it. Just don't forget to cancel you Worker if exception occurs.

Related

Why does my program loop on exception when debugging? [duplicate]

(This looks very similar to C# UnhandledException from another thread keeps looping, but am not trying to catch the exception here, just get the chance to log something)
I have some very simple C# code that sets up an UnhandledException event handler, then throws an exception:
class Program
{
static void Main(string[] args)
{
AppDomain currentDomain = AppDomain.CurrentDomain;
//currentDomain.UnhandledException += new UnhandledExceptionEventHandler(currentDomain_UnhandledException);
currentDomain.UnhandledException += (sender, eventArgs) =>
{
var exception = (Exception) eventArgs.ExceptionObject;
Console.WriteLine("Unhandled exception: " + exception.Message);
};
throw new AccessViolationException("Bleurgh");
}
}
It behaves as I expect from the console:
Unhandled exception: Bleurgh
Unhandled Exception: System.AccessViolationException: Bleurgh
at UnhandledExceptions.Program.Main(String[] args) in c:\code\sandbox\UnhandledExceptions\UnhandledExceptions\Program.cs:line 20
But when I attempt to debug it in Visual Studio it enters a loop, going into the event handler then dropping out to rethrow the Exception.
The same thing happens when I express the handler as a distinct static method.
Any ideas what's going on?
This is in Visual Studio 2010. EDIT: and .NET 4.
It seems to be down to the behaviour of the ExceptionAssistant specfically. When you continue, the assistant unwinds the call stack to the point at which the exception was thrown -- which causes the exception to be rethrown. I assume this is to allow you to make changes that would allow you to avoid the exception.
If under Tools\Options\Debugger\General you uncheck "Unwind the call stack on unhandled exceptions" then it'll just behave as an independent process would behave, and you'll see the process terminate.
This is how the debugger works, or shall we say, a "feature". If process is created by a debugger (F5) then debugger will prevent process termination, and point you to the line of code that would cause the process termination. Those "unhandled exceptions" are actually handled by the debugger, and so the execution never reaches to your code.
If debugger is attached to the process after the process was created (Ctrl+F5, and then attach) then debugger will eventually reach the unhandled exception "handler", but after exiting the handler it will still prevent process termination, and bring you back to the point where exception occurred.

Global exception handler with UnhandledExceptionEventArgs not working

After reading this MSDN page, I've created a global exception handler in my .net class library, for logging purposes, which looks like this:
static void OnException(object sender, UnhandledExceptionEventArgs args)
{
Exception ex = (Exception)args.ExceptionObject;
Logging.LogException(ex);
}
But then if I throw new UnauthorizedAccessException() or throw new Exception() from a method, this does not catch it at all.
The MSDN page says:
UnhandledExceptionEventArgs provides access to the exception object
and a flag indicating whether the common language runtime is
terminating. The UnhandledExceptionEventArgs is one of the parameters
passed into UnhandledExceptionEventHandler for the
AppDomain.UnhandledException event
I believe what I'm doing falls under the AppDomain (and not ThreadException)? What am I doing wrong here?
PS. I'm trying to avoid a try-catch block, since apparently it's bad practice. This class library is called from a windows service which runs periodically so I'd rather not let it 'crash' to avoid memory leaks due to unforeseen exceptions and would prefer to monitor the event logs regularly.
You will need to install the exception handler in the current app domain in order for it to fire:
AppDomain.CurrentDomain.UnhandledException += OnException;
Otherwise its just a method declaration that will never be called.
You mention that you are trying to avoid a try catch, but inside your handler, that wouldn't be a bad idea:
static void OnException(object sender, UnhandledExceptionEventArgs args)
{
try
{
Exception ex = (Exception)args.ExceptionObject;
Logging.LogException(ex);
}
catch
{
// do nothing to silently swallow error, or try something else...
}
}
...Because you don't want to explode in your error handler. Either swallow if stability is of primary importance, or try a secondary (more basic) logging method to insure that no exception falls through the cracks.
Normally, swallowing an exception silently is a poor practice, but this is inside an error handling block where failure means crashing an app.

Why is Visual Studio looping when debugging UnhandledException events

(This looks very similar to C# UnhandledException from another thread keeps looping, but am not trying to catch the exception here, just get the chance to log something)
I have some very simple C# code that sets up an UnhandledException event handler, then throws an exception:
class Program
{
static void Main(string[] args)
{
AppDomain currentDomain = AppDomain.CurrentDomain;
//currentDomain.UnhandledException += new UnhandledExceptionEventHandler(currentDomain_UnhandledException);
currentDomain.UnhandledException += (sender, eventArgs) =>
{
var exception = (Exception) eventArgs.ExceptionObject;
Console.WriteLine("Unhandled exception: " + exception.Message);
};
throw new AccessViolationException("Bleurgh");
}
}
It behaves as I expect from the console:
Unhandled exception: Bleurgh
Unhandled Exception: System.AccessViolationException: Bleurgh
at UnhandledExceptions.Program.Main(String[] args) in c:\code\sandbox\UnhandledExceptions\UnhandledExceptions\Program.cs:line 20
But when I attempt to debug it in Visual Studio it enters a loop, going into the event handler then dropping out to rethrow the Exception.
The same thing happens when I express the handler as a distinct static method.
Any ideas what's going on?
This is in Visual Studio 2010. EDIT: and .NET 4.
It seems to be down to the behaviour of the ExceptionAssistant specfically. When you continue, the assistant unwinds the call stack to the point at which the exception was thrown -- which causes the exception to be rethrown. I assume this is to allow you to make changes that would allow you to avoid the exception.
If under Tools\Options\Debugger\General you uncheck "Unwind the call stack on unhandled exceptions" then it'll just behave as an independent process would behave, and you'll see the process terminate.
This is how the debugger works, or shall we say, a "feature". If process is created by a debugger (F5) then debugger will prevent process termination, and point you to the line of code that would cause the process termination. Those "unhandled exceptions" are actually handled by the debugger, and so the execution never reaches to your code.
If debugger is attached to the process after the process was created (Ctrl+F5, and then attach) then debugger will eventually reach the unhandled exception "handler", but after exiting the handler it will still prevent process termination, and bring you back to the point where exception occurred.

Catch exception in function parameter

I am testing exception handling in my .NET application. With code below, I can log all exceptions, but I don't know how to catch them, so they are not stopping my application.
Here's the code I am using:
public class ExceptionHandler
{
public ExceptionHandler()
{
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.FirstChanceException += MyHandler2;
}
private void MyHandler2(object sender, FirstChanceExceptionEventArgs e)
{
try
{
throw e.Exception;
//this ends up in eternal loop with 'stack overflow'
}
catch (Exception exception)
{
//exception never comes here, but if the exception is
//not caught inside catch block, then it's unhandled and it stops application
}
}
}
So, how can I catch the exception e in MyHandler2 ? I can't use only catch, it must be try - catch ...
Well, of course it is not getting to the catch clause. Unintentionally, you have created a recursion:
First chance exception occurred somewhere in your program.
You handler is being triggered.
There is a first chance exception in your handler, woops! better go to my exception handler!
You handler is being triggered.
There is a first chance exception in your handler, woops! better go to my exception handler!
You handler is being triggered.
There is a first chance exception in your handler, woops! better go to my exception handler!
You handler is being triggered.
There is a first chance exception in your handler, woops! better go to my exception handler!
...
and there is your stack overflow...
As #Marc Gravell pointed out in his answer, this event is not for handling exceptions. Exceptions should be handled locally.
Take a look at this SO thread for more details.
You can't suppress exceptions in the way you are trying; this is just an opportunity to do things like logging; from MSDN:
This event is only a notification. Handling this event does not handle the exception or affect subsequent exception handling in any way.
Why do you want to throw exception again? just work on e.Exception in MyHandler2.
FirstChanceException Handler will take it before CLR and thus it will never reach to Catch block in MyHandler2 and will again call MyHandler2 and thus it will become recursive and end up in StackOverflow.
As explained by Mark:
This event is only a notification. Handling this event does not handle the exception or affect subsequent exception handling in any way.
Following is the only way to catch(get notified) it:
private void MyHandler2(object sender, FirstChanceExceptionEventArgs e)
{
//Never throw here
//throw e.Exception;
GetNotified(e.Exception);
}
Here GetNotified is a method where you can log error or send notifications (everything except throwing error).

Unhandled exceptions in BackgroundWorker

I have a small WinForms app that utilizes a BackgroundWorker object to perform a long-running operation.
The background operation throws occasional exceptions, typically when somebody has a file open that is being recreated.
Regardless of whether the code is run from the IDE or not .NET pops up an error dialog informing the user that an Unhandled exception has occurred. Compiling the code using the Release configuration doesn't change this either.
According to MSDN:
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.
I expect these exceptions to be thrown on occasion and would like to handle them in the RunWorkerCompleted event rather than in DoWork. My code works properly and the error is handled correctly within the RunWorkerCompleted event but I can't for the life of me figure out how to stop the .NET error dialog complaining about the "Unhandled exception" from occurring.
Isn't the BackgroundWorker supposed to catch that error automagically? Isn't that what the MSDN documentation states? What do I need to do to inform .NET that this error is being handled while still allowing the exception to propage into the Error property of RunWorkerCompletedEventArgs?
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.
I would add to the MSDN text:
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.
... AND the debugger will report the exception as "~Exception was unhandled by user code"
Solution: Don't run under the debugger and it works as expected: Exception caught in e.Error.
[Edit]
Judah has a great point. My example pointed out the specifics of handling the error but my code would actually cause another exception if an exception was never hit in the DoWork method. This example is OK due to the fact that we are specifically showing the error handling capabilities of the BackgroundWorker. However if you are not checking the error parameter against null then this could be your issue.
[/Edit]
I don't see the same results. Can you post a little code? Here is my code.
private void Form1_Load(object sender, EventArgs e)
{
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
worker.RunWorkerAsync();
}
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// Will cause another exception if an exception didn't occur.
// We should be checking to see if e.Error is not "null".
textBox1.Text = "Error? " + e.Error;
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i < 10; i++)
{
if (i < 5)
{
Thread.Sleep(100);
}
else
{
throw new Exception("BOOM");
}
}
}
Program Output:
Error? System.Exception: BOOM at
BackgroundException.Form1.worker_DoWork(Object
sender, DoWorkEventArgs e) in
D:\Workspaces\Sandbox\BackgroundException\BackgroundException\Form1.cs:line
43 at
System.ComponentModel.BackgroundWorker.OnDoWork(DoWorkEventArgs
e) at
System.ComponentModel.BackgroundWorker.WorkerThreadStart(Object
argument)
An interesting article that looks similar to your question. It has a section on handling exceptions.
http://www.developerdotstar.com/community/node/671
This is an old question, but I found it while Googling the same symptoms. Posting this in case someone else finds it for the same reason.
Judah's answer is right, but it isn't the only reason the "unhandled exception in user code" dialog can appear. If an exception is thrown from inside a constructor on the background thread then that exception will cause the dialog immediately, and won't be passed to the RunWorkerCompleted event. If you move the offending code outside of any constructors (to any other method) it works as expected.
I had the same problem and i was already applying the Judah answer before i found this topic after some googling.
Well, imo the Judah answer is partially correct. I found a better answer here
The debugger is making the work well, if you run the application in "real-world conditions", the RunWorkerCompleted deals with the exception as expected and the application behavior is also the expected.
I hope this answer helps.

Categories

Resources