Thread-sichere Ereignisaufrufe

Eine übliche Vorgehensweise zum Vermeiden von Rennbedingungen (in Multithread-Apps) beim Auslösen von Ereignissen ist:

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."

Das Problem (laut dem Buch) ist, dass "dieser Code vom Compiler optimiert werden könnte, um die lokale temporäre Variable vollständig zu entfernen. In diesem Fall ist diese Version des Codes identisch mit der ersten Version, sodass eine NullReferenceException weiterhin möglich ist".

Laut CLR über C # kann der Compiler hier besser gezwungen werden, den Ereigniszeiger zu kopieren.

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

Hier ändert CompareExchange den NewMail-Verweis auf null, wenn er null ist, und ändert NewMail nicht, wenn er nicht null ist. Mit anderen Worten, CompareExchange ändert den Wert in NewMail überhaupt nicht, gibt jedoch den Wert in NewMail atomar und threadsicher zurück. Richter, Jeffrey (12.02.2010). CLR über C # (S. 265). OReilly Media - A. Kindle Edition.

Ich arbeite im .Net 4.0-Framework und bin nicht sicher, wie dies möglicherweise funktionieren kann, da Interlocked.CompareExchange einen Verweis auf einen Speicherort und keinen Verweis auf ein Ereignis erwartet.

Entweder liegt ein Fehler im Buch vor oder ich habe ihn falsch interpretiert. Hat jemand diese Methode implementiert? Oder haben Sie eine bessere Möglichkeit, hier Rennbedingungen zu verhindern?

AKTUALISIEREN

Es war mein Fehler, der iterlocked Code funktioniert. Ich hatte gerade falsches Casting angegeben, aber laut Bradley (unten) ist es in .net 2.0 und höher auf Windows nicht notwendig.

Antworten auf die Frage(4)

Ihre Antwort auf die Frage