views:

114

answers:

3

Is there an easy way to trap all exceptions inside all UI event callbacks instead of calling try/catch in each callback?

Here's what I tried so far:

UI Callback:


private void btnOk_Click(object sender, EventArgs e)
{
  int x=0;
  int i=1/x;//Exception happens here.
}

entry point:


public static void Main(string[] args)
{
  try
  {
    Application.Run(new MyForm());
  }
  catch (Exception e)
  {
    Debug.Print(e.Message);
  }
}

In DebugView, I can see the DivideByZero exception. However, MyForm is closed and inoperable. I was hoping it could report the exception and continue operation. Is there a simple way to make MyForm send the exception to Debug.Print() without having to add try/catch directly to btnOk_Click (and all other UI callbacks)?

+3  A: 

No, there isn't - and it's not a good idea to try.

You really should only continue after an exception where you can handle the exception properly. In this case, the event handler knows what it is doing, and (potentially) could handle the exception, provide meaningful feedback, maintain a reasonable state, and allow the program to continue. Outside of the form, this would be impossible.

If you can't handle the exception gracefully, then you should allow the exception to propagate up, and tear down your application. Otherwise, you've left yourself in a potentially bad state, and you'll create more problems than you solve.

Putting in "global" exception handlers are helpful - but more for logging in order to see the error and correct it. They should not be used as a "catch all" to keep your application running.

Reed Copsey
A: 

You could use Postsharp for this.

That being said, it's a bad idea to catch all exceptions and continue. You can get your app in a really screwed up, unpredictable state by doing this.

NotDan
A: 

Yes, there is.

From MSDN:

http://msdn.microsoft.com/en-us/library/system.windows.forms.application.threadexception.aspx

You should use local try/catch blocks (and liberally use try/finally, especially if you implement a global catchall) for any exceptions that you know will occur.

For example, in a local block, you should always put:

try {
...
catch( TypeOfKnownCommonException ex ) {
...
}

The global catchall really should be used only to implement a custom error dialog and cleanup gracefully (hence liberal uses of try/finally) and prevent the microsoft error dialog from popping up.

Bob
SetUnhandledExceptionMode does NOT allow this to happen. It changes what the behavior is for unhandled exceptions, but does not allow program execution to continue. (It just changes the thread exception policy).
Reed Copsey
Oh, you're right. I meant to reference:Application.ThreadExceptionAnything caught there will allow the program to continue executing. I'll update my link.
Bob
It doesn't continue on from where it went - it just keeps that specific thread from tearing down the app. If that's your UI thread, though, you'll still shut down.
Reed Copsey