Well, I disagree. This is a matter of philosophy -- I don't think there
are objective, unequivocable arguments in either direction -- but I don't
really see the advantage of one over the other, and my preference is that
the less code one writes, the less likely one is to write buggy code.
If I write some code, I want it to add some real value to the user.
Replacing the standard Microsoft "process terminating" dialog with one's
own doesn't seem to add any real value for the user. In fact, while I
don't know the details my understanding is that Microsoft has a reporting
system tied to that dialog that, if you present your own dialog, you
completely shortcut. I realize most software authors probably don't avail
themselves of the reporting system, but it's there nonetheless.
It's my feeling that if all you're going to do when you catch an exception
globally, or receive report of it via some event, is to shut down the
application then, well...Windows can shut down the application just as
well as you can.
It would probably be helpful to read the documentation pages for those
events. I'd start with the high-level discussion of exceptions in managed
And then of course look at the documentation for the specific events.
First, _neither_ event really "catches" exceptions. They are events that
are raised when unhandled exceptions occur. Generally, UnhandledException
is for dealing with exceptions in non-GUI threads, while ThreadException
is raised for exceptions in GUI threads. Subscribing to ThreadException
does in fact change the behavior of the application if an unhandled
exception occurs, but it's still not really handling the exception.
Since I don't use either myself (see above regarding my philosophical bent
with respect to this issue :) ), I can't really offer much precise
discussion about the events. But my understanding is that with
ThreadException, you can in fact suppress termination of the application
due to an exception raised during the processing of a window message if
you subscribe to the event. With UnhandledException, it not being
relevant for GUI threads, this doesn't happen. An exception in a non-GUI
thread will cause the application to terminate regardless.
You can theoretically try anything you want. For ThreadException, since
the message pump hasn't been shut down, any UI stuff should work. For
UnhandledException, you would need to start up a new message pump (either
explicitly, or by showing a dialog modally), but you could probably get
some UI to happen.
But why would you? Shut down database connections? Those will go away
soon enough once the process has been terminated. How can you be sure you
can shut them down cleanly? What if the exception occurred while you were
already trying to shut them down cleanly, and you had a bug in your code
that prevented that from happening correctly?
The problem with thinking that you can do something to recover from these
kinds of exceptions is that by definition, they were unexpected and you
have no reason to believe that _any_ of your data is in a consistent
state. It could be that none of the data is corrupted, or it could be
that all of it is. And heaven help you if your code's execution path
depends on the data (as is very commonly the case), which means that you
have no idea what code is safe to execute except that which is entirely
independent of your data (and what use would executing that code be?).
So, the best you can do is perhaps log an error to a file (a file
dedicated to the purpose of logging unexpected exceptions like this,
guaranteed to be unrelated to whatever exception occurred). And in fact,
in some cases this is definitely a useful thing. If you have a close
relationship with your users and they can be relied upon to provide such a
file and to discuss with you the nature of the exception, this sort of
thing can be very useful.
So, it's not that there's no use for this sort of global exception
handling. It's just that I feel people should be realistic about what
sorts of things can be done when dealing with exceptions in a global way.
IMHO, recovery is not a likely option.