繁体   English   中英

C#:线程安全事件

[英]C#: Thread-safe events

下面的实现是否是线程安全的? 如果不是我错过了什么? 我应该在某个地方使用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);
    }
}

注意: 我有私有事件和显式接口的原因是因为它是一个抽象基类。 从它继承的类不应该直接对该事件做任何事情。 添加了类包装器,使其更清晰=)

您也需要在获取处理程序时锁定,否则您可能没有最新值:

protected void OnProcessingCompleted(ProcessCompletedEventArgs e)
{
    EventHandler<ProcessCompletedEventArgs> handler;
    lock (completedEventLock) 
    {
        handler = ProcessCompleted;
    }
    if (handler != null)
        handler(this, e);
}

请注意,这不会阻止竞争条件,我们已经决定执行一组处理程序, 然后取消订阅一个处理程序。 它仍然会被调用,因为我们已经将包含它的多播委托提取到handler变量中。

除了让处理程序本身意识到它不应再被调用之外,你可以做很多事情。

最好不要尝试使事件成为线程安全的 - 指定订阅应在引发事件的线程中更改。

私有ProcessCompleted成员不需要成为一个event - 它可能只是一个字段: private EventHandler<ProcessCompletedEventArgs> ProcessCompleted; - 在课堂内,它总是直接进入战场,所以无论如何event都会丢失。

你已经有一个明确的锁定对象显示的方法是没有更多的线程安全不仅仅是一个具有字段类事件(即public event EventHandler<ProcessCompletedEventArgs> ProcessCompleted; -唯一的区别是,你是不是锁定“这个“(这是一件好事 - 理想情况下你应该避免this锁定)。”处理程序变量“方法是正确的,但仍然存在应该注意的副作用

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM