Поток безопасных событий

Обычная практика, позволяющая избегать состояния гонки (в многопоточных приложениях) при запуске событий, заключается в следующем:

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

Проблема (согласно книге) заключается в том, что «этот код может быть оптимизирован компилятором для полного удаления локальной временной переменной. Если это произойдет, эта версия кода будет идентична первой версии, поэтому исключение NullReferenceException все еще возможно & quot;

Согласно CLR через C #, здесь есть лучший способ заставить компилятор скопировать указатель на событие.

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.

Я на платформе .Net 4.0, и не уверен, как это может работать, потому что Interlocked.CompareExchange ожидает ссылку на местоположение, а не ссылку на событие.

Либо в книге есть ошибка, либо я ее неправильно истолковал. Кто-нибудь реализовал этот метод? Или есть лучший способ предотвратить гонки здесь?

ОБНОВИТЬ

это была моя ошибка, замкнутый код работает. я просто указал неправильное приведение, но согласно Брэдли (ниже) это не обязательно в .net 2.0 и выше на окнах.

Ответы на вопрос(4)

Ваш ответ на вопрос