(译)构建Async同步基元,Part 3 AsyncCountdownEvent
最近在学习.NET4.5关于“并行任务”的使用。“并行任务”有自己的同步机制,没有显示给出类似如旧版本的:事件等待句柄、信号量、lock、ReaderWriterLock……等同步基元对象,但我们可以沿溪这一编程习惯,那么这系列翻译就是给“并行任务”封装同步基元对象。翻译资源来源《(译)关于Async与Await的FAQ》
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同步基元,Part 3 AsyncCountdownEvent
在我之前的两篇文章中,我已经构建了AsyncManualResetEvent 和AsyncAutoResetEvent同步基元,在这篇文章中我要创建一个简单的AsyncCountdownEvent。
CountdownEvent是这样一个事件,它允许多个等待者在接收到特定数量的信号后才完成等待。“倒计时事件”思想来自于fork/join模式(Fork/Join模式:分而治之,然后合并结果,这么一种编程模式),通常设计为:初始化一定数量的参与者,而当他们都发出事件信号时,这个倒计时从原始值变为0。当倒计时为0时CountdownEvent变成有信号状态,并且所有的等待者可以完成。
这是我们将构建的目标类型:
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,然后调用AsyncManualResetEvent的set()方法。
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》
作者:滴答的雨
出处:http://www.cnblogs.com/heyuquan/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
欢迎园友讨论下自己的见解,及向我推荐更好的资料。
本文如对您有帮助,还请多帮 【推荐】 下此文。
谢谢!!! (*^_^*)
技术群:(339322839广西IT技术交流),欢迎你的加入