的代码示例“如何:定义事件访问器方法”
http://msdn.microsoft.com/en-us/library/dw1dtw0d.aspx
似乎在没有锁定的情况下改变内部pE
。 (看起来Delegate::Combine
没有任何可以防止问题的神奇事物。)它也可以
void raise() {
if (pE != nullptr)
pE->Invoke();
}
如果pE
在支票和null
之间更改为Invoke()
,则可能会出现问题。我有两个问题:
我是否认为现有代码不是线程安全的?
因为我想要一个线程安全的代码版本,所以我想锁定add
和remove
函数。是否过早优化使用
void raise() {
MyDel^ handler = pE;
if (handler != nullptr)
handler->Invoke();
}
或者我也应该锁定该功能?
答案 0 :(得分:1)
在自定义事件实现方面,您需要同步add
和remove
访问者。只需在实现中放置一个互斥锁即可。但是,没有必要通过调用Delegate::Combine
然后转换since operator +
and -
are overloaded for delegate handles来抛弃类型安全。或者你可以无锁,如下:
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示例是完全垃圾。实现线程安全的最简单方法是使用自动实现的事件。