从线程池中加入线程

3

我有30个可以并行执行的任务。
我为每个任务使用线程池。
但是父函数在所有任务完成之前不应该返回。

我需要一个线程同步句柄,当其计数达到0时会释放WaitOne。 类似于:

foo.StartWith(myTasks.Count);
foreach (var task in myTasks) {
    ThreadPool.QueueUserWorkItem(state => { task(state); foo.Release(); });
}
foo.WaitOne();

Semaphore 似乎是正确的,只是不知道如何在这里应用它。


不是作为答案,而是离题一下,如果您使用BeginInvoke而不是线程池项来开始这些任务,您可以从AysncResults获取WaitHandles,并在它们上调用WaitAll。如果线程池的优势大于此,则这不是一个很好的答案,但如果不是,则值得考虑。 - Jon Hanna
3个回答

11
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原语。


2
或者使用4.0版本的Task类,更好的解决问题。 - Hans Passant

0
根据这篇文章:同步原语概述 C#为此场景提供了内置类型CountDownEvent:CountdownEvent类 或者类似的类型:Barrier (.NET Framework) 对于较新版本,请使用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.
*/

来自https://msdn.microsoft.com/zh-cn/library/hh228603.aspx


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接