我们都知道在多线程环境中处理 .NET 事件时的问题。其中之一是当我们尝试调用事件而不复制到局部变量时:
if (MyEvent != null)
MyEvent(this, EventArgs.Empty);
在这种情况下,如果在一个线程检查 MyEvent != null 之后,另一个线程取消订阅事件处理程序,我们可以获得竞争条件。(然后 MyEvent 试图触发和操作 .. NullRefException)
解决方案(由 J.Richter 提出)是将事件处理程序复制到局部变量:
var handler = MyEvent;
if (handler != null)
handler(this, EventArgs.Empty);
这很好用,因为
但据我所知,AMD64 JIT 做了一些优化,可以忽略本地副本并读取事件处理程序的实际值。(一篇文章很旧,但我找不到任何关于此类问题的实际信息)。
那么,在这种情况下,CLR JIT 究竟是如何工作的呢?可以有 NullReferenceException 吗?