Suppose I have a method which changes the state of an object, and fires an event to notify listeners of this state change:
public class Example
{
public int Counter { get; private set; }
public void IncreaseCounter()
{
this.Counter = this.Counter + 1;
OnCounterChanged(EventArgs.Empty);
}
protected virtual void OnCounterChanged(EventArgs args)
{
if (CounterChanged != null)
CounterChanged(this,args);
}
public event EventHandler CounterChanged;
}
The event handlers may throw an exception even if IncreaseCounter
successfully completed the state change. So we do not have strong exception safety here:
The strong guarantee: that the operation has either completed successfully or thrown an exception, leaving the program state exactly as it was before the operation started.
Is it possible to have strong exception safety when you need to raise events?
To prevent an exception in a handler from propagating to the event generator, the answer is to manually invoke each item in the MultiCast Delegate (i.e. the event handler) inside of a try-catch
All handlers will get called, and the exception won't propagate.
public EventHandler<EventArgs> SomeEvent;
protected void OnSomeEvent(EventArgs args)
{
var handler = SomeEvent;
if (handler != null)
{
foreach (EventHandler<EventArgs> item in handler.GetInvocationList())
{
try
{
item(this, args);
}
catch (Exception e)
{
// handle / report / ignore exception
}
}
}
}
What remains is for you to implement the logic for what do do when one or more event recipients throws and the others don't. The catch() could catch a specific exception as well and roll back any changes if that is what makes sense, allowing the event recipient to signal the event source that an exceptional situation has occurred.
As others point out, using exceptions as control flow isn't recommended. If it's truly an exceptional circumstance, then by all means use an exception. If you're getting a lot of exceptions you probably want to use something else.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With