下面的实现是安全的吗?如果不是的话,我错过了什么?我应该在某个地方使用volatile关键字吗?还是OnProcessingCompleted方法中某个地方的锁?如果是,在哪里?
public abstract class ProcessBase : IProcess
{
private readonly object completedEventLock = new object();
private event EventHandler<ProcessCompletedEventArgs> ProcessCompleted;
event EventHandler<ProcessCompletedEventArgs> IProcess.ProcessCompleted
{
add
{
lock (completedEventLock)
ProcessCompleted += value;
}
remove
{
lock (completedEventLock)
ProcessCompleted -= value;
}
}
protected void OnProcessingCompleted(ProcessCompletedEventArgs e)
{
EventHandler<ProcessCompletedEventArgs> handler = ProcessCompleted;
if (handler != null)
handler(this, e);
}
}注意:我之所以拥有私有事件和显式接口,是因为它是一个抽象的基类。从它继承的类不应该直接处理该事件。添加了类包装器,这样它就更清晰了
发布于 2009-06-24 11:39:51
私有ProcessCompleted成员不需要成为一个event --它可能只是一个字段:private EventHandler<ProcessCompletedEventArgs> ProcessCompleted; --在类中它总是直接进入字段,所以不管怎么说,event内容都丢失了。
使用显式锁对象所展示的方法并不比只具有类似字段的事件(即public event EventHandler<ProcessCompletedEventArgs> ProcessCompleted; --唯一的区别是您没有锁定"this“(这是一件好事--理想情况下应该避免锁定this))更安全。“处理程序变量”方法是正确的,但仍然存在你应该注意到的副作用。
发布于 2009-06-24 11:40:13
您也需要在获取处理程序时锁定,否则可能没有最新值:
protected void OnProcessingCompleted(ProcessCompletedEventArgs e)
{
EventHandler<ProcessCompletedEventArgs> handler;
lock (completedEventLock)
{
handler = ProcessCompleted;
}
if (handler != null)
handler(this, e);
}请注意,这并不会阻止我们决定执行一组处理程序,然后再执行一个未订阅的处理程序的争用条件。它仍将被调用,因为我们已经将包含它的多播委托提取到handler变量中。
除了让处理程序自己意识到不应该再调用它之外,您对此无能为力。
可以说,最好不要试图使事件线程安全--指定订阅只应在线程中更改,这将引发事件。
https://stackoverflow.com/questions/1037811
复制相似问题