EventHandler:这段代码在做什么?

5
这段代码添加了用于名为NewMail的事件的新EventHandler(s)(事件参数类名为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 via C#,第11章 事件) 我不理解的是do部分,首先我们将newMail赋值给prevHandler,然后newMail在CompareExchange中被更改为newHandler?然后我们检查newMail!= prevHandler吗?
我真的有点困惑。有人能帮我理解这里到底发生了什么,特别是在do循环中吗?

1个回答

3
正如注释所说,这是为了在多线程环境中提供一种安全的处理事件的方式。实际上这非常棘手,但下面是它的工作原理:
- Interlocked.CompareExchange做了什么:如果prevHandler == this.NewMail,则this.NewMail = newHandler。 - 整个操作(比较+影响)是原子的,即一次性完成(不能被另一个线程在操作过程中停止)。 - 如果NewMail不等于prevHandler,则意味着另一个线程已经运行了相同的代码并修改了事件处理程序。因此我们在这里不会做任何事情,而是循环并尝试再次执行,希望下一次没有其他线程已经注册了事件处理程序(下一次我们将重新读取事件处理程序;其他线程执行的操作现在将被考虑)。
另请参见这个有用的线程

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接