C# Join和WaitAll的比较

C# Join和WaitAll的比较,c#,.net,multithreading,C#,.net,Multithreading,对于多线程等待,有人能比较一下使用WaitHandle.WaitAll和Thread.Join的优缺点吗?WaitAll机制涉及内核模式对象。我不认为对于连接机制也是如此。如果有机会,我宁愿加入 但从技术上讲,这两者并不等同。IIRCJoin只能在一个线程上操作Waitall可以保留多个内核对象的信令。WaitHandle.Waitall有64个句柄限制,因此这显然是一个巨大的限制。另一方面,在一次呼叫中等待多个信号是一种方便的方式Thread.Join不需要创建任何额外的WaitHandle实

对于多线程等待,有人能比较一下使用
WaitHandle.WaitAll
Thread.Join
的优缺点吗?

WaitAll机制涉及内核模式对象。我不认为对于连接机制也是如此。如果有机会,我宁愿加入


但从技术上讲,这两者并不等同。IIRC
Join
只能在一个线程上操作
Waitall
可以保留多个内核对象的信令。

WaitHandle.Waitall
有64个句柄限制,因此这显然是一个巨大的限制。另一方面,在一次呼叫中等待多个信号是一种方便的方式
Thread.Join
不需要创建任何额外的
WaitHandle
实例。由于它可以在每个线程上单独调用,所以64句柄限制不适用

就我个人而言,我从未使用过
WaitHandle.WaitAll
。当我想等待多个信号时,我更喜欢一种更具伸缩性的模式。您可以创建一个向上或向下计数的计数机制,一旦达到某个特定值,就可以发出单个共享事件的信号。
CountdownEvent
类方便地将所有这些打包到一个类中

var finished = new CountdownEvent(1);
for (int i = 0; i < NUM_WORK_ITEMS; i++)
{
  finished.AddCount();
  SpawnAsynchronousOperation(
    () =>
    {
      try
      {
        // Place logic to run in parallel here.
      }
      finally
      {
        finished.Signal();
      }
    }
}
finished.Signal();
finished.Wait();
var finished=新的倒计时事件(1);
对于(int i=0;i
{
尝试
{
//在这里放置并行运行的逻辑。
}
最后
{
完成。信号();
}
}
}
完成。信号();
完成。等等();
更新:

您希望从主线程发出事件信号的原因很微妙。基本上,您希望将主线程视为另一个工作项。毕竟,它与其他实际工作项同时运行

请考虑一下,如果我们不将主线程作为工作项来处理,可能会发生什么情况。它将执行
for
循环的一次迭代,并向事件添加计数(通过
AddCount
)表明我们有一个挂起的工作项,对吗?假设
SpawnAsynchronousOperation
完成并将工作项排入另一个线程的队列。现在,想象一下,如果主线程在循环的下一个迭代之前被抢占。执行工作项的线程将获得其公平的CPU份额,并启动h汇总并实际完成工作项。工作项中的
信号
调用将运行并将挂起的工作项计数减为零,这将把
倒计时事件的状态更改为有信号。同时,主线程将唤醒并完成循环的所有迭代,并点击
等待
校准l、 但是,由于事件过早地得到了信号,所以即使仍有挂起的工作项,它也会传递过去


同样,当您将主线程视为一个工作项时,避免这种微妙的竞争条件是很容易的。这就是为什么
CountdownEvent
用一个计数初始化,并且在
Wait
之前调用
Signal
方法的原因。我喜欢@Brian的答案作为两种机制的比较

如果您使用的是.Net 4,那么实现任务并行性是值得探索的,通过它,您可以在更高的抽象级别上跨多个线程管理任务。您在本问题中提出的管理线程交互的信号是隐藏的或大大简化的,您可以集中精力正确定义每个Ta的内容sk由三部分组成,以及如何协调它们

这可能看起来有些离题,但正如微软自己在MSDN文档中所说:

在.NET Framework 4中,任务是 编写的首选API 多线程、异步和 并行代码


@皮特:好问题!我更新了我的答案,并做了详细的解释。