wordpress站内搜索插件,网站管理程序,wordpress在 分栏,做的asp网站手机号码传送门#xff1a;异步编程系列目录……
最近在学习.NET4.5关于“并行任务”的使用。“并行任务”有自己的同步机制#xff0c;没有显示给出类似如旧版本的#xff1a;事件等待句柄、信号量、lock、ReaderWriterLock……等同步基元对象#xff0c;但我们可以沿溪这一编程习…传送门异步编程系列目录……
最近在学习.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同步基元.rar
开始构建Async同步基元Part 4 AsyncBarrier
上一篇我们着眼于建立一个Async版本的CountdownEvent。在文章末尾我提到了一个常见模式即一个参与者发出到达信号并且等待其他参与者都发出信号“signal-and-wait”。这种典型的同步通常被称为“关卡|屏障”并且常常运用在阶段性工作场合。对于每一个阶段每一个参与者都将做一些工作然后都在关卡上“signal-and-wait”后再进入下一个阶段。
类似我们构建的AsyncCountdownEvent我们也能轻松构建一个AsyncBarrier。待构建的目标类型如下 1 2 3 4 5 public class AsyncBarrier { public AsyncBarrier(int participantCount); public Task SignalAndWait(); } 首先我们需要一些成员。像AsyncCountdown一样我们需要知道共有多少个参与者参与。但是我们不需要永久的保持该数字我们只需要知道尚未在当前阶段发出信号的参与者的剩余数量。在AsyncBarrier中每当剩余数量到达0就需要重置剩余数量为原始参与者数量所以我们需要存储原始参与者数量和尚未在当前阶段发出信号的参与者的剩余数量。我们还需要一个TaskCompletionSourcebool来创建任务所有参与者在其上等待完成。 1 2 3 private readonly int m_participantCount; private TaskCompletionSourcebool m_tcs new TaskCompletionSourcebool(); private int m_remainingParticipants; 在构造函数中将简单的初始化计数变量为我们期望的参与者数值。 1 2 3 4 5 6 public AsyncBarrier(int participantCount) { if (participantCount 0) throw new ArgumentOutOfRangeException(participantCount); m_remainingParticipants m_participantCount participantCount; } 最后我们构建SignalAndWait()先递减“剩余数量”的值当它的计数为0时我们完成TaskCompletionSourcebool。然而在这里我们需要注意操作的顺序因为一旦一个参与者从等待中唤醒它们就开始下一阶段的操作处理然后在barrier上再次“signal-and-wait”所以我们此时需要为下一阶段准备好配置即在计数为0之后且在任务完成之前我们需要重置“剩余数量”为原始参与者数量并且切换一个新的TaskCompletionSourcebool实例用于下一个阶段以便接下来唤醒所有等待者。 1 2 3 4 5 6 7 8 9 10 11 public Task SignalAndWait() { var tcs m_tcs; if (Interlocked.Decrement(ref m_remainingParticipants) 0) { m_remainingParticipants m_participantCount; m_tcs new TaskCompletionSourcebool(); tcs.SetResult(true); } return tcs.Task; } 完整源码如下 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public class AsyncBarrier1 { // 存储原始参与者数量 private readonly int m_participantCount; // 存储尚未在当前阶段发出信号的参与者的剩余数量 private int m_remainingParticipants; private TaskCompletionSourcebool m_tcs new TaskCompletionSourcebool(); public AsyncBarrier1(int participantCount) { if (participantCount 0) throw new ArgumentOutOfRangeException(participantCount); m_remainingParticipants m_participantCount participantCount; } public Task SignalAndWait() { // 临时存储当前阶段的TaskCompletionSourcebool实例 // 以便“在计数为0之后且在任务完成之前以唤醒所有等待者” var tcs m_tcs; if (Interlocked.Decrement(ref m_remainingParticipants) 0) { m_remainingParticipants m_participantCount; m_tcs new TaskCompletionSourcebool(); tcs.SetResult(true); } return tcs.Task; } } 当然还有其他方式实现AsyncBarrier。上面的设计中存在一个潜在的问题即如果所有参与者选择使用同步延续这些延续将串行化完成。处理这个问题可以留给每个参与者或者我们帮助参与者通过使每一个参与者能获得他们对应的Task再一起并行完成任务。
这样的设计类似下面封装 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 public class AsyncBarrier2 { // 存储原始参与者数量 private readonly int m_participantCount; // 存储尚未在当前阶段发出信号的参与者的剩余数量 private int m_remainingParticipants; // 线程安全的后进先出集合每一个参与者对应一个Task private ConcurrentStackTaskCompletionSourcebool m_waiters; public AsyncBarrier2(int participantCount) { if (participantCount 0) throw new ArgumentOutOfRangeException(participantCount); m_remainingParticipants m_participantCount participantCount; m_waiters new ConcurrentStackTaskCompletionSourcebool(); } public Task SignalAndWait() { var tcs new TaskCompletionSourcebool(); m_waiters.Push(tcs); if (Interlocked.Decrement(ref m_remainingParticipants) 0) { m_remainingParticipants m_participantCount; var waiters m_waiters; m_waiters new ConcurrentStackTaskCompletionSourcebool(); Parallel.ForEach(waiters, w w.SetResult(true)); } return tcs.Task; } } 这就是本节要讲的AsyncBarrier。下一节我将实现一个async版本的Semaphore。 推荐阅读 异步编程同步基元对象上 异步编程同步基元对象下 感谢你的观看……
原文《Building Async Coordination Primitives, Part 4: AsyncBarrier》
作者Stephen Toub – MSFT