Should event handlers in C# ever raise exceptions? - c#

As a general rule, are there ever any circumstances in which it's acceptable for a method responsible for listening to an event to throw an exception (or allow to be thrown) that the class raising the event will have to handle?
Given that such an exception would stop other listeners to that event from being called subsequently, it seems a bit 'antisocial' to allow this to happen, but on the other hand, if there is an exception, what should it do?

Throwing an exception from a event handler is in many ways similar to throwing an exception from a IDisposable.Dispose method (or a C++ destructor). Doing so creates havoc for your caller because you leave them with little option.
Ignore the exception and let it propagate. This breaks their contract to inform all listeners of an event. This is a very real problem if anyone above them on the stack catches the exception.
Catch it call the other handlers and rethrow. But what happens if one of the others throw as well?
Swallow the exception. This is just bad in general. Event sources should have no knowledge of their caller and hence can't know what they're swallowing.
Crash the process because you're toast.
Of all of these #4 is the best option. But this is rarely done and can't be counted on.
I think in your component you really only have a few options
You are calling the code which is throwing and are in the best position to handle the exception. If it's not handleable by you then it's unreasonable to expect it to be handled by anyone else. Hence crash the process and be done with it.
Don't call the API which throws

The only two types of exceptions that should come out of events are serious, potentially process-ending ones like System.OutOfMemoryException or System.DllNotFoundException, and things that are clearly programming errors, like System.StackOverflowException or System.InvalidCastException. Catching and dropping these kinds of exceptions is never a good idea -- let them float up to the top and let the developer decide what to do with them on an application level.
As for the rest... any common or garden-variety exception like System.IO.IOException should be handled inside your event, and you should have some mechanism for returning such error conditions to the caller.

Some of the answers here suggest it's bad to throw from an event handler ("creates havoc for your caller", "tends to lead to very difficult to handle situations, and unexpected behavior",...).
IMHO this is nonsense.
In the general case, it's perfectly OK to throw from an event handler. Other event handlers won't run of course - neither will the event handler that throws run to the end, nor any other code between the firing of the event and the point where it's caught. So what? It's perfectly normal that code is not executed when an exception is thrown - if you need to guarantee it's executed, then use a finally block.
Of course in any specific case you may want to consider which, if any, exceptions it is appropriate to handle, just as you would with any other code.
As always, there are no hard and fast rules that apply in all circumstances. One of the answers here says "event handlers should be fast ... and close to error free...". A counterexample is the ASP.NET Page.Load event.
A general rule in .NET is that it's almost always a bad idea to swallow all exceptions: this applies to event handlers just as it does to any other code.
So the answer to the original question "are there ever any circumstances in which it's acceptable for a method responsible for listening to an event to throw an exception" is very definitely yes.
Just as the answer to the question "are there ever any circumstances in which it's acceptable for a method responsible for listening to an event to swallow exceptions" is also yes.

In an ideal world, event handlers shouldn't raise exceptions. Raising an exception in an event handler tends to lead to very difficult to handle situations, and unexpected behavior. As you mentioned- this blocks subsequent event handlers from seeing the event, and the exception propagates into the event producer's code since it raised the event.
Ideally, event handlers should be fast (if they're long running, they should try to schedule the work in a separate thread) and as close to error free as possible.

In an ideal word, exceptions should not exist. In a developer real word, exceptions are always expected and should be intercepted (caught), propagated or inhibited as situation asks.
So
are there ever any circumstances in
which it's acceptable for a method
responsible for listening to an event
to throw an exception
Yes. You can expect an exception from every method, responsible or not to an event.
To catch almost every exception from a Windows application use:
AppDomain.CurrentDomain.UnhandledException
Application.ThreadException

Related

How to crash on unhandled Task exception?

I'd like to properly understand the consequences of failing to observe an exception thrown on a Task used in a fire and forget manner without exception handling.
Here's an extract from CLR via C#, Third Edition by Jeffry Richter: "[...] when a Task object is garbage collected, its Finalize method checks to see if the Task experienced an unobserved exception; if it has, Task's Finalize method throws [an exception]. Since you cannot catch an exception thrown by the CLR's finalizer thread, your process is terminated immediately."
I am writing some test code to bring about a termination but am unable to cause one.
Using the test code here, I am able to see the TaskScheduler.UnobservedTaskException handler being called. However, if I comment out the event handler subscription, the exception appears to be swallowed and does not bring about termination of the program.
I've tried this using the .NET Framework on both versions 4 and 4.8 with a Release build.
How do I demonstrate that failing to observe an exception thrown on a Task does indeed cause a crash?
The problem is correctly identified by Jon Skeet in his comment to the original post.
The best resource I found concerning this topic is by Stephen Toub.
tldr:
"To make it easier for developers to write asynchronous code based on Tasks, .NET 4.5 changes the default exception behavior for unobserved exceptions. While unobserved exceptions will still cause the UnobservedTaskException event to be raised (not doing so would be a breaking change), the process will not crash by default. Rather, the exception will end up getting eaten after the event is raised, regardless of whether an event handler observes the exception. This behavior can be configured, though. A new CLR configuration flag may be used to revert back to the crashing behavior of .NET 4, e.g."
<configuration>
<runtime>
<ThrowUnobservedTaskExceptions enabled=”true”/>
</runtime>
</configuration>

AppDomain.UnhandledException automatically re-throws handled exception

I'm trying to catch all unhandled exceptions in my app in order to conditionally handle those that can be without terminating the app, but I cannot solve a very basic problem: it doesn't stop the exception. An unhandled exception is thrown somewhere in the code, it comes here, the message box is shown, and then the application either shows that the same exceptions was unhandled (if in debug mode) or just crashes (if run without debugging). Meaning that the exception stays unhandled even though the handler was called.
App() {
AppDomain.CurrentDomain.UnhandledException += (s, a) => {
var ex = (Exception)a.ExceptionObject;
MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
};
}
This is from a new, blank test project that has nothing in it but this code and a button that throws exception when clicked.
You are forgetting to terminate your program. So it continues on with the normal unhandled exception handling. Add this line:
Environment.Exit(System.Runtime.InteropServices.Marshal.GetHRForException(ex));
The slightly laborious Marshal call ensures that another process that obtains the Process.ExitCode for your process gets a reasonable error indication. It is optional, merely recommended.
From MSDN:
This event provides notification of uncaught exceptions. It allows the application to log information about the exception before the system default handler reports the exception to the user and terminates the application. If sufficient information about the state of the application is available, other actions may be undertaken — such as saving program data for later recovery. Caution is advised, because program data can become corrupted when exceptions are not handled.
In other words, it's just a handler to allow you to tell the user what happened, produce last minute save information if you need to be able to recover data, or do something like fire off a custom error report. It is not a catch block. To catch exceptions you have to use Try-Catch.
If this is really the behaviour that you want you could add the following to your application configuration file:
<legacyUnhandledExceptionPolicy enabled="1"/>
See Exceptions in Managed Threads.
It is not supposed to "stop" the exception, that behavior is by design:
This event provides notification of uncaught exceptions. It allows the application to log information about the exception before the system default handler reports the exception to the user and terminates the application.
Consider this the place were nobody else has bothered to handle the exception in question, there is nothing sensible left to do but log and die.
You should deal with those exceptions that should terminate the application closer to where they occur.
You aren't actually catching the unhandled exceptions but merely handling an event that occurs right before terminating the application (in release mode). Subscribing to this event doesn't count as catching an already unhandled exception.
From MSDN:
This event provides notification of uncaught exceptions. It allows the application to log information about the exception before the system default handler reports the exception to the user and terminates the application. If sufficient information about the state of the application is available, other actions may be undertaken — such as saving program data for later recovery. Caution is advised, because program data can become corrupted when exceptions are not handled.

How does ASP.NET handle unhandled exceptions?

When writing for ASP.NET and, while the debugger is attached, if you visit a web page that throws an exception, the unhandled exception helper is launched at the line of code that caused the exception.
This occurs even if you only are catching unhandled exceptions and are not catching thrown exceptions. However, hitting F5, ignoring the exception, or not having the debugger attached does not cause the AppDomain to be torn down. Instead somehow ASP.NET handles the unhandled exception anyway.
How does this work, and can exception handling like this be implemented elsewhere so that other unhandled exceptions can be swallowed rather than kill the whole AppDomain or process?
Edit: To clarify, I understand how exception handling and try...catch blocks work. However, in this case it seems that the debugger is considering the exception unhandled while at the same time ASP.NET is wrapping the exception in a try...catch. That is the behavior I want to emulate.
How does this work,
asp.net just wraps executing code in whatever exception-handling code they want. asp.net webpage (or view, or controller) is just a class, and how to use it is entirely up to host (in our case, asp.net).
why does VS debugger break on it if it's handled?
There's a quote from MSDN documentation:
ASP.NET has a top-level exception handler that handles exceptions to show error pages to browser users. That top-level exception handler will stop an unhandled exception from breaking into the debugger unless Just My Code is turned on. Make sure that you enable Just My Code for ASP.NET debugging.
Which means that if you have "Just my code" enabled in VS Debug options (and it's enabled by default) you'll break at exceptions that are unhandled in your own code, irregardless of whether they are handled in your caller or not.
can exception handling like this be implemented elsewhere so that other unhandled exceptions can be swallowed rather than kill the whole AppDomain or process?
You can't do that, it is a security measure.
Your webpage is just a bunch of method calls from IIS & the ASP.NET Runtime, you're webpage isn't running alone in your appdomain. The code calling into your code has an ordinary try/catch block around that method call.
You could create a similar setup yourself:
For a ConsoleApplication, by placing a try/catch block around eveything in Main, meaning that you'l catch any exceptions that aren't handled elsewhere in your app.
For a Windows Forms application, by handling the Application.ThreadException event (Which allows you to hook into Windows Forms' message loop's try/catch block)
For a WPF appliaction, by handling the Application.DispatcherUnhandledException event (Which allows you to hook into WPF's message loop's try/catch block)
... or maybe you could use the AppDomain.UnhandledException event
The problem with these kinds of programs then would be: Where in the app should you continue?
The last question is solved easily in ASP.NET, since every page call is isolated from each other. The user just continues by navigating to a page again.

Where are exceptions best caught?

In a Winforms C# application, it seems like a good idea to catch exceptions in the GUI event methods such as button clicks, since this where all user action in an application begins.
If I put try-catch-finally clauses in the event methods then surely all my exceptions can be caught and dealt with appropriately?
Right?
In general, you should only catch exceptions that you know how to actually handle. You should catch them as close as possible to where they occur (because at that point, you know what the exception actually means).
If you are only catching exceptions in order to log them (and if this is a WinForms application), then I would use the Application.ThreadException event.
There are several ways to do it..
I prefer creating my error handler and throw all the exceptions from the code instead of catching it at that level.
Look at another post on how to handle them via Global Handler:
Where are exceptions best caught?
catches should be placed as close to the throwing source as possible. If your button click calls into your business layer which does some file processing, the business layer will better know how to recover from a FileNotFoundException than your button click handler.
Please check http://msdn.microsoft.com/en-us/library/system.windows.forms.application.threadexception.aspx
public static void Main(string[] args){
// Add the event handler for handling UI thread exceptions to the event.
Application.ThreadException += new ThreadExceptionEventHandler(ErrorHandlerForm.Form1_UIThreadException);
// Set the unhandled exception mode to force all Windows Forms errors to go through
// our handler.
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
// Add the event handler for handling non-UI thread exceptions to the event.
AppDomain.CurrentDomain.UnhandledException +=
new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
// Runs the application.
Application.Run(new ErrorHandlerForm());}
Typically, the best advice is to catch exceptions where they can best be handled, and generally to favor catching them earlier if possible.
The reason is that an exception represents an error state that the code throwing it does not know how to deal with (if it did, then it would have dealt with the error). As a simple example, say you throw a NullReference exception. The coding throwing has no idea why the reference it needs is null. Maybe it's supposed to be, but the code doesn't account for it. Or maybe there's an error in your logic farther up that passes the null down.
Catching everything at the highest level, the UI events, is a good fallback to prevent exceptions from being exposed to the user, but it's a bad practice to get accustomed to because it obscures the real reasons why exceptions are being thrown and makes it difficult to figure out where the error should be corrected at.
yes your are. but Exception is for,
Catch specific exception to general exception.
[updated]
If exception is from different thread then it won't . right point, thanks " Brian Rasmussen" ;)
A try block will operate on any uncaught exceptions thrown by code within the try block. This includes methods you call, any methods those methods call, and so on. If the exception is thrown from one of those methods, it will "bubble up" through the program, breaking out of loops, methods, etc. until it reaches the last (i.e. deepest) try block to enclose it.
You could say that from the time you enter the try block until the time you leave it, any exceptions will immediately break out of the try and have the opportunity to be handled by it (unless they're caught by other try blocks nested inside it).
So to answer your question, if you know any exceptions are going to happen inside the event handler (or in methods called from inside that event handler), then wrapping the whole thing inside a try-catch-finally block will catch any exceptions (assuming an untyped catch).
Whether this is a good idea or not is a question of design. It usually isn't. You normally want to put your error-handlers fairly close to where the error might get thrown. However, without knowing your situation or your code, it's hard to give you any advice on design details like this.
Not to forget AppDomain.UnhandledException. I always handle this one, too, when doing central exception handling.

CLR exits when a thread gets unhandled exception

I have background threads in my application. When one of the threads gets an exception that is not handled the entire CLR exits.
Is it normal behavior, or is it a bug in the CLR?
I would expect that the thread will exit but the CLR will continue working.
The default behavior in .NET applications is to exit whenever an unhandled exception occurs. When an exception goes unhandled, the program is in an unknown and possibly unsteady state. Just because it happened in a background thread doesn't mean that the error won't affect the rest of the program. The most prudent course for the runtime in that situation is to dump the program.
You might look into AppDomain.CurrentDomain.UnhandledException, which will allow you to catch unhandled exceptions and react accordingly. A better solution is to wrap your thread proc with a try...catch. But only have it handle those exceptions it knows how to handle. Doing this:
void MyThreadProc()
{
try
{
// ...
}
catch
{
// handle all exceptions
// This is a BAD idea
}
}
Is a really bad idea, because it can mask exceptions that you really do want to be propagated to the main program.
Your expected behavior used to be the behavior back in 1.1. It was generally considered to have been a bad idea. When you have an unhandled exception in any thread, your process can be left in an inconsistent state. Updates to shared data may be partially applied, etc. The runtime doesn't have the information to safely handle this scenario, or even know how you want to handle this scenario, so its choice would amount to terminating the thread and leaving your program in a strange state. This could lead to resource leaks, hangs, corruption of data, etc. By terminating the process given an unhandled exception you know exactly what happens, the process ends.
This is a normal behavior of the CLR from v2.0. Here is a MSDN post on this. To avoid process from terminating you could use something like this
<legacyUnhandledExceptionPolicy enabled="1"/>
which is not advisable.
It is normal behavior. Perhaps you want to catch the exception to prevent the application from exiting.

Categories

Resources