簡體   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