c# - Join 和 WaitAll 的比较

标签 c# .net multithreading

对于多线程等待,谁能比较一下使用WaitHandle.WaitAllThread.Join的优缺点?

最佳答案

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();

更新:

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

考虑一下如果我们不将主线程视为工作项会发生什么。它将通过 for 循环的一次迭代并向我们的事件添加一个计数(通过 AddCount)表明我们有一个待处理的工作项,对吗?假设 SpawnAsynchronousOperation 完成并使工作项在另一个线程上排队。现在,想象一下如果主线程在转向循环的下一次迭代之前被抢占。执行工作项的线程获得其公平的 CPU 份额并开始嗡嗡作响并实际完成工作项。工作项中的 Signal 调用运行并将我们的待处理工作项计数递减为零,这会将 CountdownEvent 的状态更改为已发出信号。与此同时,主线程唤醒并完成循环的所有迭代并触发 Wait 调用,但由于事件过早地发出信号,即使仍有待处理的工作项,它也会继续传递。

同样,当您将主线程视为工作项时,避免这种微妙的竞争条件很容易。这就是为什么 CountdownEvent 被初始化为一个计数并且 Signal 方法在 Wait 之前被调用。

关于c# - Join 和 WaitAll 的比较,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4191020/

相关文章:

c# - 有没有办法获取div的样式属性?

C# - AdjustTokenPrivileges 不适用于 32 位

c# - 通过 .net 反射仅获取 protected 成员

c# - 使用JavaScript从Com Visible dll调用.net dll时出错

python - 作为库开发人员,如何防止用户跨多个线程/进程使用对象?

python - 有没有办法同时执行多个函数,但是从列表中执行?

c++ - 我应该使用静态工作池还是动态工作池(线程)?

c# - 如何将实体映射到包含层次结构的维度表?

c# - Dotnet Windows 服务使用托管代码设置恢复选项

c# - 为什么在某些浏览器中我的 Session 对象得到了错误的值?