Andy's observations as he continues to attempt to know all that is .NET...

Thursday, January 31, 2008

Safe Event snippet


This week Im teaching the course I co-wrote with Kevin Jones "Code Smarter with Design Patterns in .NET", as part of the course we introduce the observer pattern and whilst the first part of the deck deals with the basic principles we soon move on to the prefered way of doing it in .NET using delegates/events.

When using events in a multi threaded environment care needs to be taken as whilst register/unregister of the events is thread safe, care needs to be taken when raising the event.


Typically we see code like this


Public class Subject


public event EventHandler<EventArgs> Alert;


    // ...


    protected virtual void OnAlert(EventArgs args)


        If ( Alert != null )


            Alert( this , args )





Here a check is being made to make sure the delegate chain has at least one instance, however whilst this works in a single threaded environment in a multithreaded environment there is a race condition between the if and the firing of the event.


To get around this problem, one way is to take a local copy of the delegate reference, and compare that. Since register/unregister events build new lists thus making the register/unregister thread safe. However there is a simpler approach and that is to use the null pattern


public event EventHandler<EventArgs> Alert = delegate { };


This will simple create a delegate instance at the head of the delegate chain which is never removed. Thus its then safe to simply do


    Alert( this , args )


Without checking for null, since that can't happen. Ok there is an overhead, but it certainly makes the logic simpler and less prone to occasional hard to find race conditions. Remembering to do this could be a pain so I wrote a simple snippet to do it...So now I simply type safeevent TAB TAB and I always get an event with a null handler...another great use of anonymous methods...



No comments:

About Me

My photo
Im a freelance consultant for .NET based technology. My last real job, was at Cisco System were I was a lead architect for Cisco's identity solutions. I arrived at Cisco via aquisition and prior to that worked in small startups. The startup culture is what appeals to me, and thats why I finally left Cisco after seven years.....I now filll my time through a combination of consultancy and teaching for Developmentor...and working on insane startups that nobody with an ounce of sense would look twice at...