Events 在C++/CLI如何定义线程安全事件访问器?
代码示例“如何:定义事件访问器方法”位于 似乎在不锁定的情况下对内部Events 在C++/CLI如何定义线程安全事件访问器?,events,thread-safety,c++-cli,Events,Thread Safety,C++ Cli,代码示例“如何:定义事件访问器方法”位于 似乎在不锁定的情况下对内部pE进行变异。(它看起来不像是Delegate::Combine做了任何可以防止问题发生的神奇事情。)它也做了 void raise() { if (pE != nullptr) pE->Invoke(); } 如果检查和调用()之间的pE更改为null,则会出现问题。我有两个问题: 现有代码不是线程安全的,我说得对吗 因为我想要一个线程安全版本的代码,所以我考虑锁定add和remove函数。使用优化
pE
进行变异。(它看起来不像是Delegate::Combine
做了任何可以防止问题发生的神奇事情。)它也做了
void raise() {
if (pE != nullptr)
pE->Invoke();
}
如果检查和调用()之间的pE
更改为null
,则会出现问题。我有两个问题:
add
和remove
函数。使用优化是否过早
void raise() {
MyDel^ handler = pE;
if (handler != nullptr)
handler->Invoke();
}
或者我也应该锁定该函数添加
和删除
访问器的想法是正确的。只需在实现周围放置一个互斥体。但是没有必要通过调用Delegate::Combine
然后强制转换来丢弃类型安全性。或者您可以不上锁,如下所示:
void add(MyDel^ p)
{
MyDel^ old;
MyDel^ new;
do {
old = pE;
new = pE + p;
} while (old != Interlocked::CompareExchange(pE, new, old));
}
必要时定义删除(new=pE-p;
)。您为raise
提供的代码对于自定义事件实现来说非常合适
总之,该MSDN样本是全部垃圾。实现线程安全的最简单方法是使用自动实现的事件。可能重复的Thank:-)出于好奇,侦听器是否有办法确保其删除()
本身的尝试已成功?@seek:while
循环在成功删除之前不会退出。除非您指的是侦听器是否在订户列表中,否则在这种情况下,事件访问器不会提供任何方式让您返回该信息。但是您当然可以创建一个单独的方法来检查new.GetInvocationList()->Count!=old.GetInvocationList()->Count
是的,我指的是后者。我想知道raise()。不过,似乎我们需要将p
标记为volatile,以确保完全正确。