Background Worker Event Handling - c#

I've been struggling with event handling in backgroundworker threads.
All the documentation I've come across make me believe that when a DoWork event handler throws an exception that exception should be dealt with in the RunWorkerCompleted handler and that exception will be available in the Error property of the RunWorkerCompletedEventArgs.
This is fine, but during debug time I always see an exception unhandled by user code message. This makes me believe there is a problem with my approach.
What steps should I take to resolve this?
Regards,
Jonathan

I've seen this behavior before, and I've gotten around it by decorating the DoWork handler with the System.Diagnostics.DebuggerNonUserCode attribute:
[System.Diagnostics.DebuggerNonUserCode]
void bw_DoWork(object sender, DoWorkEventArgs e)
{ ... }
Note that you'll only see this if you're running in the debugger; even without the attribute, all is as it should be when running from the shell.
I looked this up again, and I still can't see any good reason why you need to do this. I'm calling it a debugger misfeature.

I've had this problem before. The e.Error only gets set when you don't run in Debug mode. If you run in Debug, exectuion stops at the spot of the Exception. However, run the same program in Non debug mode (in VS Debug -> Start Without Debugging or Ctrl+F5) and the nasty exception dialog WON'T come up, and e.Error will be the exception. Not sure why, but that's how it works....

Your approach is correct. Just press continue on the message and keep going. If in doubt, test it outside of a debug session.

Related

in C# can I have code execute when an exception is thrown?

I've got a bug that is really difficult for me to track. It's one of those that only occurs when the debugger isnt connected :)
I've pinvoked MiniDumpWriteDump() and that works really well for creating .dmp files that I can debug after the fact.
however, I'm doing something like
try
{
foo();
}
catch(Exception)
{
CreateMiniDump()
}
this works great, however I dont get the callstack that is desired. I'd really prefer to have the callstack (with all the member variables) at the point where the exception was thrown.
is this possible? Is there a mechanism to get first dibs on the exception? such that I can create a minidump and preserve the callstack, etc?
In .NET 4 and up you can subscribe to the FirstChanceException event.
You can subscribe to AppDomain.CurrentDomain.UnhandledException to get an event that is raised when an exception is about to unwind. When it's raised, the original context is still on the stack. You could put your minidump creation code inside of your event handler.

Hijacking UnhandledException to keep Multi-Threaded Application Running

Situation
Well, as you can see below, I have a main App, creating a thread, which creates a bunch of background workers. When the RunWorkerCompleted is fired on some BG worker, I sometimes end up dropping an Unhandled Exception, (for a reason I have clearly pinpointed, but this is not the matter).
So the Logs clearly show that my UnhandledException handler is entered and reports the exception.
I know I am deliberately misusing the OnUnhandledException by stopping the App from exiting, using a Console.Read(). I did it on purpose because I want a human intervention/check before terminating the app.
public static void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Logger.log("UNHANDLED EXCEPTION : " + e.ExceptionObject.ToString());
Mail.Sendmail("ADMIN ALERT : " + e.ExceptionObject.ToString());
Console.Read(); // Yes, this is an ungraceful trick, I confess.
}
However, what was supposed just to be a "pause" before manual exit turned out to keep the App alive, ie, the Thread is still generating workers, and running as if nothing happened.
Even Weirder : The UnhandledException is still being dropped from time to time when it happens again. And it is logged each time, behaving just as if it was a plain ol' try catch.
(This was the default behaviour before .Net 3.0)
Question
So, why is everything happening as if the UnhandledException was not thrown, and the thread and BG's keeping running as if nothing happened ? My guess is that as long as the OnUnhandledException handler is not done, and the App is still alive, all running threads that are still alive keep on living in a free world and doing their job.
This gives me a bad temptation, which is to keep this design, as a try/catch to unHandled Exception. I know this is not a tidy idea, as you never know if the exception is serious or something that could be skipped. However, I would really prefer my program to keep running all day and watch the log report / mail alerts and decide for myself if it needs to be restarted or not.
As this is a server application that needs to be running 24/7 I wanted to avoid ill-timed and repetitive interruptions due to minor still unhandled exceptions.
The biggest advantage to that being that the server program keeps running while we are tracking down unhandled exceptions one by one and deliver patches to handle them as they occur.
Thank you for your patience, and please feel free to give feedback.
PS : No, I did not smoke pot.
My guess is that as long as the OnUnhandledException handler is not
done, and the App is still alive, all running threads that are still
alive keep on living in a free world and doing their job.
Correct. But your other threads are now doing their job in a potentially unstable process. There are good reasons for terminating the App when an unhandled exception happens.
I would really prefer my program to keep running
Besides the (potential) stability problems, you would accumulate the halted state of whatever is involved in the unhandled handling. My guess is that you would at least leak a Thread each time it happens. And you can't spare too many of them.
So it would be a very bad design, and only delay the crashing.
First of all you need to subscribe the UnhadledThreadException handler. There you can not "Hijack" the exception, but you have access to it and also to the thread it belongs. What you can do now is putting the throwing Thread into suspetion. The Thread will be still alive!!
This however is a bad, dirty hack! Do not do this!
Take a look at this article for some details.
I recommend switching your threading model to TPL (design remains). There you have access to those ugly cross-thread excepions and can handle/supress em gracefully.
If you want to allow a BackgroundWorker thread to fail without killing the whole process, there's a cleaner way to do this.
First, intercept the RunWorkerCompleted event. This event is raised when the BackgroundWorker thread terminates, either normally or via an unhandled exception. Then in your event handler, check for the unhandled exception:
// Runs when the BackgroundWorker thread terminates.
private void ThreadFinished(object sender, RunWorkerCompletedEventArgs e)
{
// Process any unhandled exception
if (e.Error != null)
{
this.LogError(e.Error.Message, e.Error.StackTrace, blah, blah);
In this way, you can let the BackgroundWorker thread die and log any exception without terminating the whole process.

how to avoid windows crash screen

We have UnhandledExceptionEventHandler in place and unexpected exceptions were caught by that handler. But why we still see the following screen? I thought if we handled the exception, it will not go up to the OS. If no exception reach the system level, why that screen still show up?
Registering an UnhandledExceptionEventHandler with AppDomain.UnhandledException does not mean that unhandled exceptions become handled. Instead, it is a mechanism to be able to log the exception and relevant program state to aid in later debugging. The exception will remain unhandled and Windows Error Reporting will be invoked.
In reality, when this event is invoked it's "too late" for the the exception to be handled. Assuming you could tell the runtime to continue execution, where would execution unwind to? Not a single frame on the call stack wanted to handle the exception. At best, the executing thread could be terminated; but what if it's on the only foreground thread? Better to propagate the unhandled exception to the operating system's default unhandled exception filter and let it invoke Windows Error Reporting.
Edit with some additional comments:
Now, certain applications you want to design to be crash-resistant, such as long-running service processes. It may make sense to add "catch-all"* exception handlers in some cases, such as a job queue that executes jobs and it doesn't matter if an individual job fails with an unhandled exception; we log the problem and move on to the next job. However, a root catch-all handler in something like Main makes little sense: your entire application is now in an unknown state. You could log the exception and terminate, but you'd be missing out on the benefits of Windows Error Reporting: post-mortem minidumps and an easy button (the "Debug" button on that dialog) to invoke the registered JIT debugger that will take you directly to the problem. For most software, my advice is to simply let your software crash; in-your-face bugs with minidumps are usually some of the easiest to fix.
*Some exceptions are inherently "uncatchable", such as a StackOverflowException. Others, such as an AccessViolationException are catchable, but are inherently indicative of a serious program state incongruity (couldn't read or write from an expected memory location). It is never a good idea to attempt recovery from such exceptions.
Click the Debug button to see where the exception comes from.
If you don't see it immediately, start your application in Visual Studio, go to the Debug,Exceptions dialog, and check all exceptions. Then rerun your application, investigate the code every time the debugger tells you that a first-chance exception has been encountered, and pass the exception to the application if Visual Studio asks you whether to do this.
This should help you finding the source of the problem.
That's because your unhandled exception occurs in the main thread, and there is almost nothing to do about it. Check this article: What!? A .NET Application Can Die?
Almost nothing, yes, because you can still catch that exception on the Application.Run level. At this point your application is dead anyway, but at least you can "avoid windows crash screen" and implement your own crash screen instead:
static void Main()
{
try
{
Application.Run(new Form1());
}
catch (Exception ex)
{
MessageBox.Show("Oops! Can I has " + ex.Message + "?");
}
}
There are cases when unhadled exceptions will not be handled by UnhandledExceptionEventHandler. For example System.Timers.Timer is swallowing exceptions, so they are not propagated to UnhandledExceptionEventHandler.

Avoid "program stopped working" in C#/.NET

I have a console application written in C#/.NET that I want to run from a script (nant). If an exception occurs in the console application, I would like nant to continue, but in Windows Vista there is a popup that searches for solutions and asks for debug etc.
I would like to avoid the popup with "program stopped working" when an exception happens in the console application. How can I control this from C#/.NET?
(A similar question addresses the issue for the C language, but I would like a solution for C#/.NET.)
(To clarify: I would like the exception to be passed to nant, but without the popup.)
The JIT debugger popup occurs when there's an unhandled exception. That is, an exception tunnels all the way up the stack to the root of any thread in the runtime.
To avoid this, you can handle the AppDomain.CurrentDomain.UnhandledException event and just call Environment.Exit(1) to exit gracefully.
This will handle all exceptions on all threads within your AppDomain. Unless you're doing anything special, your app probably only has one AppDomain, so putting this in your public static void Main method should suffice:
AppDomain.CurrentDomain.UnhandledException += (sender, args) =>
{
Console.Error.WriteLine("Unhandled exception: " + args.ExceptionObject);
Environment.Exit(1);
};
You should probably use the NAnt logger to write out the error in this case too (can't recall the API for this offhand though.)
You can also disable JIT debugging on the machine. I would only recommend this in certain circumstances such as for a dedicated build server.
Under Windows Vista you can disable this dialog for your programms.
Disable the "Problem Reports and Solutions feature". You find it under Control Panel-->Problem Reports and Solutions-->Change Settings-->Advanced Settings-->Turn off for my programs, problem reporting
Just catch the exception and log/ignore it.
The popup appears due to an unhandled exception. To avoid that make sure your main method captures all exceptions and turn them into some other useful piece of info you can pick up. Just ignoring the exception is not recommended.
Btw remember that exceptions are per thread, so if your application spawns threads or uses thread pool threads, you need a handler for these too.
Usually this only happens when your app doesnt handle an exception. If you wrap your whole console app in a try/catch bblock, and just pass back a fail code, then you will avoid this.
Sometimes, a windows application will stop working if you are using a System.Timers.Timer.
To fix this, change System.Timers.Timer by System.Windows.Forms.Timer
Greetings

Unhandled Exception Handler in .NET 1.1

I'm maintaining a .NET 1.1 application and one of the things I've been tasked with is making sure the user doesn't see any unfriendly error notifications.
I've added handlers to Application.ThreadException and AppDomain.CurrentDomain.UnhandledException, which do get called. My problem is that the standard CLR error dialog is still displayed (before the exception handler is called).
Jeff talks about this problem on his blog here and here. But there's no solution. So what is the standard way in .NET 1.1 to handle uncaught exceptions and display a friendly dialog box?
Jeff's response was marked as the correct answer because the link he provided has the most complete information on how to do what's required.
Oh, in Windows Forms you definitely should be able to get it to work. The only thing you have to watch out for is things happening on different threads.
I have an old Code Project article here which should help:
User Friendly Exception Handling
Unhandled exception behavior in a .NET 1.x Windows Forms application depends on:
The type of thread that threw the exception
Whether it occurred during window message processing
Whether a debugger was attached to the process
The DbgJitDebugLaunchSetting registry setting
The jitDebugging flag in App.Config
Whether you overrode the Windows Forms exception handler
Whether you handled the CLR’s exception event
The phase of the moon
The default behavior of unhandled exceptions is:
If the exception occurs on the main thread when pumping window messages, it's intercepted by the Windows Forms exception handler.
If the exception occurs on the main thread when pumping window messages, it will terminate the app process unless it's intercepted by the Windows Forms exception handler.
If the exception occurs on a manual, thread-pool, or finalizer thread, it's swallowed by the CLR.
The points of contact for an unhandled exception are:
Windows Forms exception handler.
The JIT-debug registry switch DbgJitDebugLaunchSetting.
The CLR unhandled exception event.
The Windows Form built-in exception handling does the following by default:
Catches an unhandled exception when:
exception is on main thread and no debugger attached.
exception occurs during window message processing.
jitDebugging = false in App.Config.
Shows dialog to user and prevents app termination.
You can disable the latter behavior by setting jitDebugging = true in App.Config. But remember that this may be your last chance to stop app termination. So the next step to catch an unhandled exception is registering for event Application.ThreadException, e.g.:
Application.ThreadException += new
Threading.ThreadExceptionHandler(CatchFormsExceptions);
Note the registry setting DbgJitDebugLaunchSetting under HKEY_LOCAL_MACHINE\Software.NetFramework. This has one of three values of which I'm aware:
0: shows user dialog asking "debug or terminate".
1: lets exception through for CLR to deal with.
2: launches debugger specified in DbgManagedDebugger registry key.
In Visual Studio, go to menu Tools → Options → Debugging → JIT to set this key to 0 or 2. But a value of 1 is usually best on an end-user's machine. Note that this registry key is acted on before the CLR unhandled exception event.
This last event is your last chance to log an unhandled exception. It's triggered before your Finally blocks have executed. You can intercept this event as follows:
AppDomain.CurrentDomain.UnhandledException += new
System.UnhandledExceptionEventHandler(CatchClrExceptions);
AppDomain.UnhandledException is an event, not a global exception handler. This means, by the time it is raised, your application is already on its way down the drain, and there is nothing you can do about it, except for doing cleanup and error logging.
What happened behind the scenes is this: The framework detected the exception, walked up the call stack to the very top, found no handlers that would recover from the error, so was unable to determine if it was safe to continue execution. So, it started the shutdown sequence and fired up this event as a courtesy to you so you can pay your respects to your already-doomed process. This happens when an exception is left unhandled in the main thread.
There is no single-point solution to this kind of error. You need to put a real exception handler (a catch block) upstream of all places where this error occurs and forward it to (for example) a global handler method/class that will determine if it is safe to simply report and continue, based on exception type and/or content.
Edit: It is possible to disable (=hack) the error-reporting mechanism built into Windows so the mandatory "crash and burn" dialog does not get displayed when your app goes down. However, this becomes effective for all the applications in the system, not just your own.
Is this a console application or a Windows Forms application? If it's a .NET 1.1 console application this is, sadly, by design -- it's confirmed by an MSFT dev in the second blog post you referenced:
BTW, on my 1.1 machine the example from MSDN does have the expected output; it's just that the second line doesn't show up until after you've attached a debugger (or not). In v2 we've flipped things around so that the UnhandledException event fires before the debugger attaches, which seems to be what most people expect.
It sounds like .NET 2.0 does this better (thank goodness), but honestly, I never had time to go back and check.
It's a Windows Forms application. The exceptions that are caught by Application.ThreadException work fine, and I don't get the ugly .NET exception box (OK to terminate, Cancel to debug? who came up with that??).
I was getting some exceptions that weren't being caught by that and ended up going to the AppDomain.UnhandledException event that were causing problems. I think I've caught most of those exceptions, and I am displaying them in our nice error box now.
So I'll just have to hope there are not some other circumstances that would cause exceptions to not be caught by the Application.ThreadException handler.
The Short Answer,
Looks like, an exception occurring in Form.Load doesn't get routed to Application.ThreadException or AppDomain.CurrentDomain.UnhandledException without a debugger attached.
The More accurate Answer/Story
This is how I solved a similar problem. I can't say for sure how it does it, but here is what I think. Improvement suggestions are welcome.
The three events,
AppDomain.CurrentDomain.FirstChanceException
AppDomain.CurrentDomain.UnhandledException
and Application.ThreadException
accumulatively catch most of the exceptions but not on a global scope (as said earlier). In one of my applications, I used a combination of these to catch all kinds of exceptions and even the unmanaged code exceptions like DirectX exception (through SharpDX). All exceptions, whether they are caught or not, seem to be invoking FirstChanceException without a doubt.
AppDomain.CurrentDomain.FirstChanceException += MyFirstChanceExceptionHandler;
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); // not sure if this is important or not.
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; // can't use Lambda here. need to Unsub this event later.
Application.ThreadException += (s, e) => MyUnhandledExceptionHandler(e.Exception);
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
MyUnhandledExceptionHandler((Exception)e.ExceptionObject);
}
private void CurrentDomain_FirstChanceException(object sender, System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs eventArgs)
{
// detect the pattern of the exception which we won't be able to get in Fatal events.
if (eventArgs.Exception.Message.StartsWith("HRESULT"))
MyUnhandledExceptionHandler(eventArgs.Exception);
}
and the handler looks like
static void MyUnhandledExceptionHandler(Exception ex)
{
AppDomain.CurrentDomain.UnhandledException -= MyUnhandledExceptionHandler; // this is important. Any exception occuring in the logging mechanism can cause a stack overflow exception which triggers the window's own JIT message/App crash message if Win JIT is not available.
// LogTheException()
// Collect user data
// inform the user in a civil way to restart/close the app
Environment.Exit(0);
}
Unmanaged code exceptions like DirectX exceptions appeared only in FirstChanceException where I had to decide for myself if the exception was fatal or not. I then use MyUnhandledExceptionHandler to log and let the user know in a friendly way that everything was "under control".
IMPORTANT NOTE!
The scheme still didn't catch one kind of exception. It did appear in FirstChanceException, but it was hard to distinguish it from other kinds of exceptions hitting this handler. Any exception occurring directly in Form.Load had this different behavior. When the VS debugger was attached, these were routed to the UnhandledException event. But without a debugger, an old-school windows message will pop up, showing the stack trace of the exception that occurred. The most annoying thing was that it didn't let MyUnhandledExceptionHandlerr get kicked once it was done and the app continued to work in an abnormal state. The final solution I did was to move all the code from Form_load to another thread using MyForm.Load += (s,e) => new Thread(()=>{/* My Form_Load code*/ }).Start();. This way, Application.ThreadException gets triggered which is routed to MyUnhandledExceptionHandler, my safe exit.

Categories