线程安全的事件调用方式

通常事件调用方式为

//版本1

public event NewEventHandler NewEvent;
protected virtual void OnNewEvent(EventArgs e)
{
  if (NewEvent != null) NewEvent(this, e);
}

但这种方式的问题在于,在做NewEvent != null 检测之后,NewEvent事件调用之前,事件取消了注册,即NewEvent重新变成null,此时再进行调用,将会抛出异常

线程安全的做法,

//版本2

protected virtual void OnNewEvent(EventArgs e)
{
  NewEventHandler temp = Volatile.Read(ref NewEvent);
       if (temp != null) temp(this, e);
}

用一个temp变量来存储NewEvent。

Volatile.Read强迫读取NewEvent,保证复制到temp中,免得编译器将语句: NewEventHandler temp = NewEvent; 中的temp优化掉。

(但这其实一般不会发生,JIT编译器一般不会这么做)

 

posted @ 2017-06-22 22:59  wangyijunwyj  阅读(134)  评论(0编辑  收藏  举报