我有30多个可以并行执行的任务 我为每项任务使用ThreadPool 但是在完成所有任务之前,父函数不应该返回。
我需要一个线程同步句柄,当它的计数达到0时会释放WaitOne。 类似的东西:
foo.StartWith(myTasks.Count);
foreach (var task in myTasks) {
ThreadPool.QueueUserWorkItem(state => { task(state); foo.Release(); });
}
foo.WaitOne();
Semaphore
感觉正确,只是无法弄清楚如何在这里应用它。
答案 0 :(得分:9)
int running = myTasks.Count;
AutoResetEvent done = new AutoResetEvent(false);
foreach (var task in myTasks) {
ThreadPool.QueueUserWorkItem(state => {
task(state);
if (0 == Interlocked.Decrement(ref running))
done.Set ();
});
}
done.WaitOne();
使用C#4.0,您可以使用新的CountdownEvent原语。
答案 1 :(得分:0)
Joe Duffy写了一篇关于此类事情的精彩文章:
CLR Inside Out: 9 Reusable Parallel Data Structures and Algorithms
我正在将CountdownLatch视为特别适合您的要求。
答案 2 :(得分:0)
根据这篇文章:Overview of Synchronization Primitives
C#具有此场景的内置类型,CountDownEvent:CountdownEvent Class
对于较新版本,请使用TPL(任务并行库),对于此场景,此代码是相关的:
// Create an ActionBlock<int> object that prints its input
// and throws ArgumentOutOfRangeException if the input
// is less than zero.
var throwIfNegative = new ActionBlock<int>(n =>
{
Console.WriteLine("n = {0}", n);
if (n < 0)
{
throw new ArgumentOutOfRangeException();
}
});
// Post values to the block.
throwIfNegative.Post(0);
throwIfNegative.Post(-1);
throwIfNegative.Post(1);
throwIfNegative.Post(-2);
throwIfNegative.Complete();
// Wait for completion in a try/catch block.
try
{
throwIfNegative.Completion.Wait();
}
catch (AggregateException ae)
{
// If an unhandled exception occurs during dataflow processing, all
// exceptions are propagated through an AggregateException object.
ae.Handle(e =>
{
Console.WriteLine("Encountered {0}: {1}",
e.GetType().Name, e.Message);
return true;
});
}
/* Output:
n = 0
n = -1
Encountered ArgumentOutOfRangeException: Specified argument was out of the range
of valid values.
*/