A common practice to avoid race conditions (in multi-threaded apps) when triggering events is this:

EventHandler<EventArgs> temp = SomeEvent; if (temp != null) temp(e); "Remember that delegates are immutable and this is why this technique works in theory. However, what a lot of developers don't realize is that this code could be optimized by the compiler to remove the local temp variable entirely. If this happens, this version of the code is identical to the first version, so a NullReferenceException is still possible."

The problem (according to the book) is that "this code could be optimized by the compiler to remove the local temp variable entirely. If this happens, this version of the code is identical to the first version, so a NullReferenceException is still possible"

According to CLR via C#, here is a better way to force the compiler to copy the event pointer.

virtual void OnNewMail(NewMailEventArgs e) { EventHandler<NewMailEventArgs> temp = Interlocked.CompareExchange(ref NewMail, null, null); if (temp != null) temp(this, e); }

Here, CompareExchange changes the NewMail reference to null if it is null and does not alter NewMail if it is not null. In other words, CompareExchange doesn't change the value in NewMail at all, but it does return the value inside NewMail in an atomic, thread-safe way. Richter, Jeffrey (2010-02-12). CLR via C# (p. 265). OReilly Media - A. Kindle Edition.

I am on .Net 4.0 framework, and not sure how this can possibly work, because Interlocked.CompareExchange expects a reference to a location, not a reference to a event.

Either there is an error in the book, or I misinterpreted it. Has anyone implemented this method? Or have a better way to prevent race conditions here?

UPDATE

it was my mistake, the iterlocked code works. i just had wrong casting specified, but according to Bradley (below) it is not necessary in .net 2.0 and up on windows.