Matthew Scharley
Matthew Scharley

Reputation: 132294

Why do exceptions propogate out of an event handler?

Consider the following program. How is the behaviour that it displays (namely that exceptions will propagate out of an event handler) a "good thing"? As far as I can tell, it could only ever be bad; unexpected exceptions popping up from functions that they shouldn't. In my particular case, it was killing threads. So, is this behaviour actually a good thing in some cases? Is this a reason to say that letting exceptions out of event-handlers is poor design?

static class Program {
    static void Main()
    {
        Foo foo = new Foo();
        foo.SomeEvent += ThrowException;

        try 
        {
            foo.OnSomeEvent();
        } 
        catch (Exception) 
        {
            // This is printed out
            Console.WriteLine("Exception caught!");
        }
    }

    static void ThrowException(object sender, EventArgs e)
    {
        throw new Exception();
    }
}

// Define other methods and classes here
class Foo 
{
    public event EventHandler SomeEvent;

    public void OnSomeEvent()
    {
        SomeEvent(this, EventArgs.Empty);
    }
}

Upvotes: 4

Views: 7525

Answers (6)

Martin Kunc
Martin Kunc

Reputation: 471

It would be the best to think about exception as part of your contract with event listeners.

Which means, if the listener is nice and catches its Exceptions (it can do that for known ones), you are OK.

For the rest, unknown exceptions, or in Java speech "Runtime exceptions", you need to be ready for them the same way as if they would occur in your code.

What I am trying to say is, if you are building a contract with the event listeners, you cannot force them to throw just one exception type (so that you can consume them) and you need to take all Exceptions seriously. After all, they are indications of "wrong states" which you don't want to hide for consumers.

Upvotes: 0

user163686
user163686

Reputation:

The main aspect of exception handling discussed here is: do not catch exception if you don't know how to handle it. But let's talk about the observer pattern, where notifier emits event (or signal) about it's state change and listeners handle it. A good example of a notifier is a button emitting 'clicked' event. Does a button care about who are the listeners and what they do? Not really. If you're a listener and you got this event, then you've got a job to do. And if you can't do it, you have to handle this error or inform user, because passing exception to the button makes no sense - button definitely does not know how to handle errors of listener job. And buttons state changer (probably some message loop) does not either - your application will end up at Main() with a crash.

That's how observer pattern works - event emitters don't know what their listeners are doing and there's very little chance they will handle this exception properly.

Also bear in mind, that if your exception handler throws exception, there may be other listeners that won't receive notification and that may lead to undefined application state.

So my advice is to catch all exceptions at event handler, but figure out how to handle them there. Or else no one will.

Upvotes: 4

Jon Skeet
Jon Skeet

Reputation: 1500993

What's your preferred alternative - silently swallowing the exception? I wouldn't like that at all.

Events are just a way of implementing the observer pattern, really. If a listener throws an exception, I'd absolutely expect that exception to be thrown back to the caller. Any other behaviour I can think of would effectively treat the exception as unimportant. The whole point of exceptions is that when something goes wrong, you find out about it quickly and implicitly. You have to explicitly handle exceptions, so that you don't go on your merry way in a corrupt state without realising it.

You make a valid point about whose responsibility it is to handle exceptions. Broadly speaking, I find it best to assume that just about anything can throw an exception at any time. Other than special cases where I know a specific exception may occur and I can handle it, I don't usually catch exceptions other than at the top level - except possibly to wrap and rethrow, or log and rethrow.

Now it's possible that one of your event handlers really shouldn't be throwing an exception - that they haven't really run into an error condition - but what should happen if it's a perfectly reasonable exception which indicates a serious problem? While a program crashing is ugly, it's often better than continuing with some of it malfunctioning, possibly corrupting persisted state etc.

Fundamentally, I don't think the CS/SE field has got error handling "right" yet. I'm not even sure that there is an elegant way of doing the right thing which is simple to express in all situations... but I hope that the current situation isn't as good as it gets.

Upvotes: 17

Adam Ruth
Adam Ruth

Reputation: 3655

An event is nothing more than syntactic sugar around a function call, so it makes sense that it would propagate up to the function that raised the event. What, otherwise, should the behaviour be? The exception has to go somewhere.

Upvotes: 0

djna
djna

Reputation: 55907

My personal prejudice is that not catching exceptions is generally a bad thing. The only "exception" to this rule for me is for simple applciations where the uncaught exception termianates the process, you see the error and fix it.

For multi-threaded apps, if the default behaviour of uncaught exceptions is to zap threads then it seems to me absurd not to catch exceptions. Hence event handlers should not just punt the exception up the stack and hope for the best.

Silently swallowing exceptions is usually bad too, something bad has happended it needs fixing. So perhaps log a message, and then return?

Upvotes: 2

sharptooth
sharptooth

Reputation: 170489

You need a contract with the event source on whether the event handler can throw exceptions. For example, if a COM object is an event source this is strictly prohibited - exceptions should never cross COM boundary.

Upvotes: 0

Related Questions