Monday, October 23, 2006

For a long time now I have been wondering how to handle a situation in which there is an unhandled exception thrown from the event handling method of my events. Given the simple pattern for raising events in the form of:

private event EventHandler SomeEvent;
protected void OnSomeEvent()
{
   
if (SomeEvent != null)
   {
      SomeEvent();
   }
}

What happens when one of the handlers of SomeMethod throws exception? Keeping in mind the internal implementation of events that I have described here, I know that this exception will go outside the SomeEvent() call and even outside the OnSomeEvent() up the call stack. It is rather obvious. What is not so obvious is one should handle such a situation?

I have spend some time searchin the Internet for some kind of guideline or best practice but I have been unable to find one. I have talked with Krzysztof Cwalina about it and it seems that there is no good solution to the problem. You can put the event invocation in the try catch block but the only kind of exception you can catch there is really the Exception - since you don't know anything about what the handler may be. Krzysztof suggests that it may be good idea to document what kind of exception you expect from the event handlers but it it only a partial solution. Other solutions include terminating the application, allowing the exception to propagate or swallowing the exception - none of those seems right to me.

If any of you knows of any proven practice on how to handle this kind of situation I would really appreciate it if you point me in the right direction.

kick it on DotNetKicks.com

Tuesday, October 24, 2006 1:12:53 PM (Central European Standard Time, UTC+01:00)
Well... if an error occur "protected void OnSomeEvent" in this method... I catch it or rethrow it whatever the exception may be or the way you handle exception. However, if the exception occur when calling "private event EventHandler SomeEvent;" I normally let the user manage it. We have to remember that event are a way to introduce code from "outside" the class. Since we don't have any control over that and it's not even "in" our code, we shall not provide any exception handling.

This is my best practice. Or did I took it from Microsoft?

Anyway... that work best that way.
Arch4ngel
Tuesday, October 24, 2006 2:54:33 PM (Central European Standard Time, UTC+01:00)
If the event is caused by something that the user does not manage such as events from operating system, your class handles those events, encapsulates some of the data and raises events on its own, which are in turn handled by user code. In this setup, user has no direct way to handle the exceptions other than not raising them himself. I'm however considering what should be done from the class point of view. The problem is that as you write your events you do not expect exception in there. So far the solution that seams best is as you suggest - not to handle the exception.
Wednesday, October 25, 2006 5:41:54 AM (Central European Standard Time, UTC+01:00)
The easier implementation of that would be using the GetInvocationList method of the event delegate, which will return you an array. You can then loop over each item enclosing it in try-catch, so that even if one fails, rest are not affected.
Rajdeep Kwatra
Wednesday, October 25, 2006 12:15:59 PM (Central European Standard Time, UTC+01:00)
My solution (still deciding if I like it or not)

Step 1:
as suggested above, use the GetInvocationList to get a list of delegates for the event

Step 2:
In try block:
For each listener, invoke the handler by using DynamicInvoke on the delegate

Step 3:
Catch any TargetInvokation exceptions that might occur from the delegate's handler.

Step 4:
capture exception information into custom EventListner class which contains the delegate + exception which occured in the delegate (innerException of targetInvokation exception).

Add custom EventListner class to a custom EventListnerException class which contains a collection of EventListner classes

Step 5:
after all delegate handlers have been invoked, check if exception occured (I check if the eventListnerException != null) ie: I only create the exception if a delegate exception occurs

Throw the eventListnerException

With this methodology the following is achieved:
1) All delegates are notified of the event
2) a trace of all exceptions (should more than one occur) are maintained
3) Since it was an unhandled exception in the first place, the exception(s) are then re-thrown for any client code to catch and analyse

My 2 cents.

Jax
Inquisitor Jax
Wednesday, October 25, 2006 12:21:24 PM (Central European Standard Time, UTC+01:00)
oh....and all this functionality I have in a utility method in my base class which has the following as parameters:
Delegate[] delegates, object sender, EventArgs e

so instead of:
protected void OnSomeEvent()
{
if (SomeEvent != null)
{
SomeEvent();
}
}

I have:
protected void OnSomeEvent(object sender, EventArgs e)
{
if (SomeEvent != null)
{
ManageEventListners(SomeEvent.GetInvocationList(), sender, e)
}
}
Inquisitor Jax
Monday, October 20, 2008 4:55:07 PM (Central European Standard Time, UTC+01:00)
Although you cannot control the code being called by a customer who is handling your event, the customer can control his own code, and thus the customer needs unfettered access to the truth.

What I'm driving at is that in practice your event will trigger code being written by a developer, who in order to write a bug free app will need to 'see' exceptions in his/her code; if you wrap the event delegate invocation in a try-catch you'll hide the bug from them.

Imagine if Microsoft couldn't trust you with their framework events?

The excessive caution of MS would actually impair your ability to find your own bugs.

Luke Puplett
Name
E-mail
Home page

Comment (Some html is allowed: a@href@title, strike) where the @ means "attribute." For example, you can use <a href="" title=""> or <blockquote cite="Scott">.  

Enter the code shown (prevents robots):

Live Comment Preview