Wednesday, May 27, 2009

A Thread-safe C# Event Invocation Pattern

It has been pointed out by several expert developers that the recommended event invocation pattern suffers from a race condition on the event's invocation list.

The workaround in the link above does, in the strictest sense, address this issue. Invocation lists are immutable. If a separate thread were to remove a handler from the original invocation list while the publisher (OnEvent...) was executing this would create a new Invocation list (one without the removed handler) while the publisher would continue using it's copied reference to the original.

Unfortunately this may not address the underlying issue: while an event is being published its list of handlers should not be modified. C# provides a way to deal with this via event accessors. By combining event accessors and basic synchronization (via lock), it's possible to make a truly thread-safe event invocation pattern:


public class EventSource
{
private EventHandler testEventHandlers;

public event EventHandler TestEvent
{
add
{
lock (testEventHandlers) { testEventHandlers += value; }
}
remove
{
lock (testEventHandlers) { testEventHandlers -= value; }
}
}

public void OnTestEvent()
{
lock (testEventHandlers)
{
if (testEventHandlers != null)
testEventHandlers(this, new EventArgs());
}
}
}

No comments :

Post a Comment