Svi*_*ish 5 c# events multithreading event-handling thread-safety
下面的实现是否是线程安全的?如果不是我错过了什么?我应该在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);
}
}
Run Code Online (Sandbox Code Playgroud)
注意:我有私有事件和显式接口的原因是因为它是一个抽象基类.从它继承的类不应该直接对该事件做任何事情.添加了类包装器,使其更清晰=)
您也需要在获取处理程序时锁定,否则您可能没有最新值:
protected void OnProcessingCompleted(ProcessCompletedEventArgs e)
{
EventHandler<ProcessCompletedEventArgs> handler;
lock (completedEventLock)
{
handler = ProcessCompleted;
}
if (handler != null)
handler(this, e);
}
Run Code Online (Sandbox Code Playgroud)
请注意,这不会阻止竞争条件,我们已经决定执行一组处理程序,然后取消订阅一个处理程序.它仍然会被调用,因为我们已经将包含它的多播委托提取到handler
变量中.
除了让处理程序本身意识到它不应再被调用之外,你可以做很多事情.
最好不要尝试使事件成为线程安全的 - 指定订阅只应在引发事件的线程中更改.
私有成员不需要ProcessCompleted
是event
- 它可能只是一个字段:private EventHandler<ProcessCompletedEventArgs> ProcessCompleted;
- 在类内部它总是直接进入该字段,所以event
无论如何东西都会丢失。
您使用显式锁定对象展示的方法并不比仅具有类似字段的事件更线程安全(即-public event EventHandler<ProcessCompletedEventArgs> ProcessCompleted;
唯一的区别是您没有锁定“this”(这是一件好事 -理想情况下,您应该避免锁定this
)。“处理程序变量”方法是正确的方法,但您仍然应该注意一些副作用。
归档时间: |
|
查看次数: |
5578 次 |
最近记录: |