(譯)構建Async同步基元,Part 3 AsyncCountdownEvent


傳送門:異步編程系列目錄……

最近在學習.NET4.5關於“並行任務”的使用。“並行任務”有自己的同步機制,沒有顯示給出類似如舊版本的:事件等待句柄、信號量、lockReaderWriterLock……等同步基元對象,但我們可以沿溪這一編程習慣,那么這系列翻譯就是給“並行任務”封裝同步基元對象。翻譯資源來源《(譯)關於AsyncAwaitFAQ

1.         構建Async同步基元,Part 1 AsyncManualResetEvent

2.         構建Async同步基元,Part 2 AsyncAutoResetEvent

3.         構建Async同步基元,Part 3 AsyncCountdownEvent

4.         構建Async同步基元,Part 4 AsyncBarrier

5.         構建Async同步基元,Part 5 AsyncSemaphore

6.         構建Async同步基元,Part 6 AsyncLock

7.         構建Async同步基元,Part 7 AsyncReaderWriterLock

 

源碼:構建Async同步基元.rar

開始:構建Async同步基元,Part 3 AsyncCountdownEvent

         在我之前的兩篇文章中,我已經構建了AsyncManualResetEvent AsyncAutoResetEvent同步基元,在這篇文章中我要創建一個簡單的AsyncCountdownEvent

         CountdownEvent是這樣一個事件,它允許多個等待者在接收到特定數量的信號后才完成等待。“倒計時事件”思想來自於fork/join模式(Fork/Join模式:分而治之,然后合並結果,這么一種編程模式),通常設計為:初始化一定數量的參與者,而當他們都發出事件信號時,這個倒計時從原始值變為0。當倒計時為0CountdownEvent變成有信號狀態,並且所有的等待者可以完成。

         這是我們將構建的目標類型:

public class AsyncCountdownEvent 
{ 
    public AsyncCountdownEvent(int initialCount); 
    public Task WaitAsync(); 
    public void Signal(); 
}

一個倒計時事件實際是由一個手動重置事件和一個內部計數實現,所以我們的AsyncCountdownEvent將還包含兩個成員:

private readonly AsyncManualResetEvent m_amre = new AsyncManualResetEvent(); 
private int m_count;

         在類型的構造函數中進行m_count變量初始化,以提供特定數量的參與者。

public AsyncCountdownEvent(int initialCount) 
{ 
    if (initialCount <= 0)
        throw new ArgumentOutOfRangeException("initialCount"); 
    m_count = initialCount; 
}

對於WaitAsync()方法我們直接委托給AsyncManualResetEvent的相應方法。

public Task WaitAsync() { return m_amre.WaitAsync(); }

       最后,我們的Signal()方法將遞減m_count變量直到值為0,然后調用AsyncManualResetEventset()方法。

public void Signal() 
{ 
    if (m_count <= 0) 
        throw new InvalidOperationException(); 
 
    int newCount = Interlocked.Decrement(ref m_count); 
    if (newCount == 0) 
        m_amre.Set(); 
    else if (newCount < 0) 
        throw new InvalidOperationException(); 
}

       AsyncCountdownEvent類型還有一個常見的模式:用它作為一種形式的關卡|屏障,一個參與者發出到達信號並且等待其他參與者到達。為了達到此目的,我們能還可以添加一個簡單的SignalAndWait()方法來實現這個常見的模式。

public Task SignalAndWait() 
{ 
    Signal(); 
    return WaitAsync(); 
}

 

這就是本節要講的AsyncCountdownEvent

完整源碼如下:

    public class AsyncCountdownEvent
    {
        // 手動重置事件
        private readonly AsyncManualResetEvent m_amre = new AsyncManualResetEvent();
        // 一個內部計數
        private int m_count;
        
        public AsyncCountdownEvent(int initialCount)
        {
            if (initialCount <= 0)
                throw new ArgumentOutOfRangeException("initialCount");
            m_count = initialCount;
        }

        public Task WaitAsync() 
        {
            return m_amre.WaitAsync();
        }

        public void Signal()
        {
            if (m_count <= 0)
                throw new InvalidOperationException();

            int newCount = Interlocked.Decrement(ref m_count);
            if (newCount == 0)
                m_amre.Set();
            else if (newCount < 0)
                throw new InvalidOperationException();
        }

        // 用它作為一種形式的關卡|屏障,一個參與者發出到達信號並且等待其他參與者到達。
        public Task SignalAndWait()
        {
            Signal();
            return WaitAsync();
        }
    }

下一節,我將實現一個async版本的Barrier

 

推薦閱讀:

                   異步編程:同步基元對象(上)

                   異步編程:同步基元對象(下)

 

感謝你的觀看……

原文:Building Async Coordination Primitives, Part 3: AsyncCountdownEvent

作者:Stephen Toub – MSFT


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM