Wait Handles和System.Threading.Tasks命名空间

时间:2012-02-23 02:17:52

标签: c# .net multithreading task

当我在Parallel.ForEach命名空间中使用Parallel.ForSystem.Threading.Tasks时,我可以假设所有线程在执行继续之前都已同步吗?

是否有相当于

的东西
WaitHandle.WaitAll(...);

继续?

所以,如果我打电话给

Parallel.ForEach(collection, DoSomethingWithObject);

DoSomethingWithObject返回之前,我可以确定每个ForEach的来电已完成,还是我需要自己使用WaitHandles

4 个答案:

答案 0 :(得分:3)

为了扩展Phong的正确答案,Parallel.For和Parallel.ForEach在内部创建了一个所谓的ParallelXXXReplicationTask,它同步运行并产生X个子任务,其中X是有效的并发级别(默认为Environment.ProcessorCount)。每个子任务与Semphore同步,Semphore一旦设置(计数为0)就释放父任务,这确保父任务的执行仅在所有子任务完成后(或通过同步设置确定崩溃/停止)返回。由于parentTask是同步运行的并且正在等待。您可以确保无论何时对Parallel方法的调用返回,所有迭代都已有效完成。

答案 1 :(得分:2)

所有任务都将在Parallel.ForEach()返回时完成,除非专门调用Stop()来中止并行执行。在这种情况下,.IsCompleted返回的ParallelLoopState对象的Parallel.ForEach()属性将为false

你可以在这里阅读:

http://msdn.microsoft.com/en-us/library/dd992001.aspx

http://msdn.microsoft.com/en-us/library/system.threading.tasks.parallelloopresult.aspx

您还可以编写一个小型测试应用程序,其中DoSomethingWithObject()是一个长时间运行的操作,或者是对Thread.Sleep()的调用,以验证这一点。执行将阻塞,直到所有线程都完成睡眠。

样品:

Parallel.ForEach(Enumerable.Range(1, 8),
    i =>
    {
        Thread.Sleep(5000);
        Console.WriteLine(i + " done!");
    });
Console.WriteLine("All done!");

答案 2 :(得分:2)

  

我可以确定每次调用DoSomethingWithObject都已完成   在ForEach返回之前,还是我需要自己使用WaitHandles?

Parallel.ForEach是一个阻止通话。在每次迭代完成之前,它不会返回。

  

是否有等同于WaitHandle.WaitAll(...);的内容?

是的,或多或少。它实际上不会使用WaitHandle.WaitAll,因为1)它会非常低效; 2)它不具有可伸缩性,因为它有64个句柄限制。有一些非常可扩展的技术可用于等待完成多个任务。我最喜欢的一个是使用CountdownEvent 1

以下是它的工作原理。用你的想象力假装Parallel.ForEach扩展为以下代码。 2

var finished = new CountdownEvent(1);
foreach (var item in collection)
{
  var capture = item;
  finished.AddCount();
  Task.Factory.StartNew(
    () =>
    {
      try
      {
        DoSomething(capture);
      }
      finally
      {
        finished.Signal();
      }
    });
}
finished.Signal();
finished.Wait();

1 我不是说这是Parallel.ForEach使用的技术,但它可能类似。

2 实际上Parallel.ForEach以更复杂的方式实施。我只是想帮助您想象它可能等待每次迭代完成的时间。

答案 3 :(得分:0)

Parallel.ForEach()Parallel.For()将阻止其所有任务结束,原因是它们已成功完成或因为已取消。所以是的,所有线程在执行继续之前都是同步的。