EventHandler:这段代码发生了什么?

时间:2012-02-05 10:43:14

标签: c# events delegates event-handling

此代码为名为NewMail的事件添加了新的EventHandler寄存器(eventargs类名为NewMailEventArgs

// A PUBLIC add_xxx method (xxx is the event name)
// Allows methods to register interest in the event.
public void add_NewMail(EventHandler<NewMailEventArgs> value) {
  // The loop and the call to CompareExchange is all just a fancy way
  // of adding a delegate to the event in a thread-safe way.
  EventHandler<NewMailEventArgs> prevHandler;
  EventHandler<NewMailEventArgs> newMail = this.NewMail;
  do {
     prevHandler = newMail;
     EventHandler<NewMailEventArgs> newHandler = (EventHandler<NewMailEventArgs>)Delegate.Combine(prevHandler, value);
     newMail = Interlocked.CompareExchange<EventHandler<NewMailEventArgs>>(ref this.NewMail, newHandler, prevHandler);
    }
  while(newMail != prevHandler);
}

(来源:CLR通过C#,第11章事件) 我不明白的是do部分,首先我们将newMail分配给prevHandler,然后newMail被更改(在CompareExchange中)到newHandler?然后我们检查newMail!= prevHandler?
我真的很困惑。任何人都可以帮助我理解这里到底发生了什么,特别是在do循环中吗?

1 个答案:

答案 0 :(得分:3)

正如评论所说,它提供了一种处理多线程环境中事件的安全方法。这实际上非常棘手,但这是它的工作原理:

  • Interlocked.CompareExchange是什么:if prevHandler == this.NewMail,然后this.NewMail = newHandler

  • 整个操作(比较+影响)是原子,即一次完成(在另一个线程的操作过程中无法停止)

  • 如果NewMail不等于prevHandler,则意味着另一个线程已经运行了相同的代码并且已经修改了事件处理程序。所以我们不会在这里做任何事情,我们将循环再试一次,希望下次 没有其他线程已经注册了一个事件处理程序(下次我们' ll 重新读取事件处理程序;现在将考虑其他线程完成的操作。

另请参阅此有用的thread