(译)构建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

posted on 2013-01-15 09:42  滴答的雨  阅读(1606)  评论(9编辑  收藏