我们都知道在多线程环境中处理.NET事件时会遇到问题。其中之一是在不将事件复制到本地变量的情况下尝试调用事件:
在这种情况下,如果一个线程检查到MyEvent != null,而另一个线程取消订阅了该事件的处理程序,就会出现竞争条件。(然后MyEvent试图触发并且出现了NullRefException)
解决方案(由J.Richter提出)是将事件处理程序复制到本地变量中:
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吗?