前几天,我遇到一个问题,一个事件在检查时不为null,但在调用时为null:
if (MyEvent != null)
MyEvent();
由于这是有缺陷的代码(MyEvent可能在检查和调用之间被另一个线程取消注册,从而触发NullReferenceException),我按照建议更改了代码:
var handler = MyEvent;
if (handler != null)
handler();
但神秘的是,这个问题仍然存在。有时我会得到一个NullReferenceException。调试器显示MyEvent为null,但处理程序不是。处理程序怎么可能仍然抛出NullReferenceException?我认为这是线程安全的代码,我错过了什么?
更新
正如我现在从这篇博文中了解到的那样:https://blogs.msdn.microsoft.com/ericlippert/2009/04/29/events-and-races/这种模式并不是真正的线程安全的。似乎在同时触发事件时注册事件可能会导致奇怪的行为。
第二个想法,这似乎并非难以置信。由于事件原则上只是要执行的方法列表,因此同时读取和写入列表可能会造成严重问题。这在Collections中是众所周知的(这就是ObservableCollections存在的原因),所以假设在事件操作时会出现同样的问题似乎是公平的。
我会深入挖掘以了解更多信息。