views:

4694

answers:

3

We are having a WPF application where parts of it may throw exceptions at runtime. I'd like to globally catch any unhandled exception and log them, but otherwise continue program execution as if nothing happened (kinda like VB's On Error Resume Next).

Is this possible in C#? And if so, where exactly would I need to put the exception handling code?

Currently I can't see any single point where I could wrap a try/catch around and which would catch all exceptions that could occur. And even then I would have left whatever has been executed because of the catch. Or am I thinking in horribly wrong directions here?

ETA: Because many people below pointed it out: The application is not for controlling nuclear power plants. If it crashes it's not that much a big deal but random exceptions that are mostly UI-related are a nuisance in the context where it would be used. There were (and probably still are) a few of those and since it uses a plugin architecture and may be extended by others (also students in that case; so no experienced developers that are able to write completely error-free code).

As for the exceptions that get caught: I do log them to a log file, including the complete stack trace. That was the whole point of that exercise. Just to counter those people that were taking my analogy to VB's OERN too literally.

I know that blindly ignoring certain classes of errors is dangerous and might corrupt my application instance. As said before, this program isn't mission-critical for anyone. No-one in their right mind would bet the survival of the human civilization on it. It's simply a little tool for testing certain design approaches wrt. software engineering.

For the immediate use of the application there are not many things that can happen on an exception:

  • No exception handling – error dialog and application exit. Experiment has to be repeated, though likely with another subject. No errors have been logged, which is unfortunate.
  • Generic exception handling – benign error trapped, no harm done. This should be the common case judged from all errors we were seeing during development. Ignoring this kind of errors should have no immediate consequences; the core data structures are tested well enough that they will easily survive this.
  • Generic exception handling – serious error trapped, possibly crash at a later point. This may happen rarely. We've never seen it so far. The error is logged anyway and a crash might be inevitable. So this is conceptually similar to the very first case. Except that we have a stack trace. And in the majority of cases the user won't even notice.

As for the experiment data generated by the program: A serious error would at worst just cause no data to be recorded. Subtle changes that change the result of the experiment ever so slightly are pretty unlikely. And even in that case, if the results seem dubious the error was logged; one can still throw away that data point if it's a total outlier.

To summarize: Yes, I consider myself still at least partially sane and I don't consider a global exception handling routine which leaves the program running to be necessarily totally evil. As said twice before, such a decision might be valid, depending on the application. In this case it was judged a valid decision and not total and utter bullshit. For any other application that decision might look different. But please don't accuse me or the other people who worked on that project to potentially blow up the world just because we're ignoring errors.

Side note: There is exactly one user for that application. It's not something like Windows or Office that gets used by millions where the cost of having exceptions bubble to the user at all would be very different in the first place already.

+1  A: 

Like "VB's On Error Resume Next?" That sounds kind of scary. First recommendation is don't do it. Second recommendation is don't do it and don't think about it. You need to isolate your faults better. As to how to approach this problem, it depends on how you're code is structured. If you are using a pattern like MVC or the like then this shouldn't be too difficult and would definitely not require a global exception swallower. Secondly, look for a good logging library like log4net or use tracing. We'd need to know more details like what kinds of exceptions you're talking about and what parts of your application may result in exceptions being thrown.

BobbyShaftoe
The point is that I want to keep the application running even after uncaught exceptions. I just want to log them (we have a custom logging framework for this, based on our needs) and don't need to abort the whole program just because some plugin did something weird in its user interaction code. From what I've seen so far it's not trivial to isolate the causes cleanly as the different parts do not really know each other.
Joey
I understand but you have to be very cautious of continuing after an exception that you do not examine, there is the possibility of data corruption and so forth to consider.
BobbyShaftoe
I agree with BobbyShaftoe. This is not the correct way to go. Let the application crash. If the fault is on some plugin, then fix or get somebody to fix the plugin. Leaving it running is EXTREMELY dangerous. You will get weird side effects and will reach a point where you won't be able to find a logical explanation for the bugs happening in your application.
Cristian Iorga
I elaborated that point a little in the question now. I know the risks involved and for that particular application it was deemed acceptable. And aborting the application for something as simple as an index out of bounds while the UI tried to do some nice animation is overkill and unneeded. Yes, I don't know the exact cause but we have data to back up the claim that the vast majority of error cases is benign. The serious ones we're masking might cause the application to crash but that's what would have happened without global exception handling anyway.
Joey
+21  A: 

Use the Application.DispatcherUnhandledException Event. Read the Global Exception-Handling for WPF blog article for a nice explanation.

Be aware that there'll be still exceptions which preclude a successful resuming of your application, like after a stack overflow, exhausted memory or lost network connectivity while you're trying to save to the database.

David Schmitt
Thanks. And yes, I am aware that there are exceptions from which I can't recover, but the vast majority of those that could happen are benign in this case.
Joey
If your exception occurs on a background thread (say, using ThreadPool.QueueUserWorkItem), this will not work.
siz
@siz: good point, but those can be handled with a normal try block around in the workitem, no?
David Schmitt
A: 

This not really thinking--yes, you probably want the application to exit. BUT, wouldn't be nice to first log the exception with its StackTrace? If all you got from the user was, "Your application crashed when I pressed this button", you may never be able to resolve the issue because you wouldn't have sufficient information. But if you first logged the exception before more pleasantly aborting the application, you will have significantly more information.

Russ
I elaborated that point a little in the question now. I know the risks involved and for that particular application it was deemed acceptable. And aborting the application for something as simple as an index out of bounds while the UI tried to do some nice animation *is* overkill and unneeded. Yes, I don't know the exact cause but we have data to back up the claim that the vast majority of error cases is benign. The serious ones we're masking might cause the application to crash but that's what would have happened without global exception handling anyway.
Joey