Połączenia z bezpiecznym wydarzeniem wątku

Powszechną praktyką unikania warunków wyścigowych (w aplikacjach wielowątkowych) jest uruchamianie zdarzeń:

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

Problem (według książki) polega na tym, że „ten kod może zostać zoptymalizowany przez kompilator, aby całkowicie usunąć lokalną zmienną temp. Jeśli tak się stanie, ta wersja kodu jest identyczna z pierwszą wersją, więc wyjątek NullReferenceExcept jest nadal możliwy”

Zgodnie z CLR za pośrednictwem C #, tutaj jest lepszy sposób zmuszenia kompilatora do skopiowania wskaźnika zdarzenia.

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

W tym przypadku CompareExchange zmienia odwołanie do NewMail na null, jeśli ma wartość null i nie zmienia NewMail, jeśli nie ma wartości NULL. Innymi słowy, CompareExchange w ogóle nie zmienia wartości w NewMail, ale zwraca wartość wewnątrz NewMail w sposób atomowy, bezpieczny dla wątków. Richter, Jeffrey (2010-02-12). CLR przez C # (s. 265). OReilly Media - A. Kindle Edition.

Jestem na platformie .Net 4.0 i nie jestem pewien, jak to może działać, ponieważ Interlocked.CompareExchange oczekuje odwołania do lokalizacji, a nie odniesienia do zdarzenia.

Albo jest błąd w książce, albo źle ją zinterpretowałem. Czy ktoś wdrożył tę metodę? A może masz lepszy sposób na uniknięcie warunków wyścigowych tutaj?

AKTUALIZACJA

to był mój błąd, kod działający z blokadą działa. Po prostu miałem niewłaściwy casting określony, ale według Bradleya (poniżej) nie jest to konieczne w .net 2.0 i wyżej w Windows.

questionAnswers(4)

yourAnswerToTheQuestion