1

代码示例“如何:定义事件访问器方法”位于

http://msdn.microsoft.com/en-us/library/dw1dtw0d.aspx

似乎在pE没有锁定的情况下改变了内部。(看起来Delegate::Combine并没有什么神奇的东西可以防止问题。)它也确实

void raise() {
   if (pE != nullptr)
      pE->Invoke();
}

如果pEnullcheck 和Invoke(). 我有两个问题:

  1. 我对现有代码不是线程安全的吗?

  2. 由于我想要代码的线程安全版本,我正在考虑锁定addandremove函数。使用是否过早优化

    void raise() {
        MyDel^ handler = pE;
        if (handler != nullptr)
           handler->Invoke();
    }
    

    还是我也应该锁定该功能?

4

1 回答 1

3

raise与您链接的页面中的示例不同,默认情况下,所有三个访问器都是线程安全的(包括空检查,并使用局部变量来避免竞争条件) 。

当涉及到自定义事件实现时,您需要同步addremove访问器是正确的。只需在实现周围放置一个互斥锁。Delegate::Combine但是没有必要通过调用然后强制转换来抛弃类型安全,因为 operator+-为委托句柄重载。或者你可以去无锁,如下:

void add(MyDel^ p)
{
     MyDel^ old;
     MyDel^ new;
     do {
         old = pE;
         new = pE + p;
     } while (old != Interlocked::CompareExchange(pE, new, old));
 }

remove比照定义( new = pE - p;)。您提供的代码raise非常适合自定义事件实现。

总之,该 MSDN 示例完全是垃圾。实现线程安全的最简单方法是使用自动实现的事件。

于 2012-07-20T20:23:42.830 回答