返回零倒数事件
我试图使用CountdownEvent只允许线程在事件的计数为零时继续,但是我希望初始计数为零。实际上,我想返回到零行为,从而当计数为零并且线程被设置为等待大于零时等待该事件。返回零倒数事件
我可以使用0初始计数来初始化倒计时事件,但是当我尝试添加计数时,我会得到InvalidOperationException“CountdownEvent_Increment_AlreadyZero”。
是否有其他类别或其他方式可以使用Countdown事件以避免此限制?
如果您可以将.NET 4.0或Reactive Extensions用于.NET 3.5(它具有.NET 4 TPL功能的反向链接),那么可以查看Barrier类。它允许您协调多个并行任务,以使它们不会继续,直到障碍中的所有参与者发出信号表示其到达为止。它也应该满足您的要求,让参与者在处理过程中出现和消失。
您写道:
我执行,这将创建一个未知号码的孩子操作(没有任务或线程)
那么,什么是他们的工作?你应该做这样的事情:
CountdownEvent ev; public void foo() { ev = new CountdownEvent(1); foreach (<task in tasks_to_start>) { ev.AddCount(); // enter code here which starts your task } ev.Signal(); ev.Wait(); } public static void youtTask(CountdownEvent ev) { // some work // ... // after all is done ev.Signal(); }
您可以使用一个队列对象,以“工作”加入到并再次冒了出来。
只有当队列为空时,你才能继续前进。
但是,我们需要细节在这里...
这会为你工作吗? http://msdn.microsoft.com/en-us/library/dd384749.aspx
编辑
对不起,这是模糊的。使用SOReader的答案,如果每个家长都有一个倒计时事件,从1开始 - 然后在孩子中使用TryAddCount递增,然后将父母递减回1,然后在孩子完成时从父母递减到1,最后递减计数父线程的父代。因此,树状系列的倒数事件。
我没有多线程的经验,但乍一看这就是我会尝试。
你的问题似乎是一个常见的树行走分叉技术。每次你都要递归时,你会发起另一个并发操作(将它排入一个线程池等)。但是你需要等待所有子支路结束。只需为每次启动的子操作添加1到倒数事件,并在每个子操作结束时发出信号。只要您安排算法,只要它为每个子操作添加算法,它就不会发出信号,这是安全的。
我应该补充说,你不要需要知道计数前面,只需使它在根1,并且每次你分叉到一个孩子,加1,然后在每个一个,它会动态处理任何树,没有前期成本。
CountdownEvent有一个方法添加它可以让您增加飞行中的计数。
这有道理吗?我可能会远离你想要完成的事情。但是,如果您确实需要按照您指定的方式运行的CountdownEvent,则可以很容易地将一些互锁操作封装在类中以执行您所说的操作。
但是,CountdownEvent的构建是羽毛重量,如果没有人在信号发出之前等待,它几乎是免费的。在昂贵的情况下,它是最优的,无论有多少任务(等),它只会让一个内核转换到信号,一个等待,最坏的情况。
为了实现你的建议,需要围绕信号和事件重置进行同步。倒计时事件依赖于一个简单的原则,只有在信号调用中从非零到零的转换才可能发出事件信号。没有竞争,因为多个线程不可能同时更改值(它是互锁的),所以只有一个线程可以尝试发信号通知事件对象(唤醒另一个等待线程)。完善。但是,如果您有多个线程设置并将其重置,则需要同步设置和重置,因为计数可能会抖动几次,并且多个线程都会同时尝试设置或重置事件。 (设置,重置和等待事件都很昂贵,因为它们都必须进行内核转换并导致上下文切换)。除非您保护设置/重置转换,否则它将无法工作。如果他们将此添加到CountdownEvent中,它将不再是几乎最佳的,它将显着更昂贵。
你有没有解决过这个问题?你是怎么做到的? – HAL9000 2011-04-15 20:31:42