【问题标题】:C# Threads, WaitHandle.WaitAllC# 线程,WaitHandle.WaitAll
【发布时间】:2010-11-25 04:28:55
【问题描述】:

这可能不会使用 WaitHandle.WaitAll(waitHandles) 阻止 winForm,而是设置另一个线程,当从 WaitHandle.WaitAll 获得 complate 信号时将触发该线程?

【问题讨论】:

  • 你应该接受你的问题的答案。

标签: c# multithreading


【解决方案1】:

我不会使用WaitHandle.WaitAll。这种方法有几个问题。

  • 有 64 个句柄限制。
  • 它不能用于 STA 线程。
  • 它促进了依赖于创建多个 WaitHandle 实例的模式,这些实例显然会消耗资源。

相反,当我想等待多个事件时,我通常使用CountdownEvent 类。现在,您将遇到的问题是它仍然需要您在某个线程上调用Wait,这正是您要避免的。避免进行阻塞调用的标准机制是使用ThreadPool.RegisterWaitForSingleObject 方法。但是,不幸的是,这需要 WaitHandleCountdownEvent 不会从该类继承。

解决方案是创建您自己的CountdownWaitHandle 类,该类可以在ThreadPool.RegisterWaitForSingleObject 方法中使用。这种方法将允许您指定一个回调委托,该委托将在WaitHandle 发出信号后执行。

这是CountdownWaitHandle 类的最基本实现。您必须自己添加所有必要的硬编码,但这会让您开始。

public class CountdownWaitHandle : WaitHandle
{
    private int m_Count = 0;
    private ManualResetEvent m_Event = new ManualResetEvent(false);

    public CountdownWaitHandle(int initialCount)
    {
        m_Count = initialCount;
    }

    public void AddCount()
    {
        Interlocked.Increment(ref m_Count);
    }

    public void Signal()
    {
        if (Interlocked.Decrement(ref m_Count) == 0)
        {
            m_Event.Set();
        }
    }

    public override bool WaitOne()
    {
        return m_Event.WaitOne();
    }
}

这里的想法是不要使用许多不同的WaitHandle 实例,而是使用单个CountdownWaitHandle 实例。使用所需计数初始化实例,然后调用Signal 以减少计数。一旦计数变为零,WaitHandle 将进入信号状态。因此,与其在多个WaitHandle 实例上调用Set 并用WaitHandle.WaitAll 阻塞,不如在这个实例上调用Signal 并通过调用WaitOne 阻塞。同样,您可以使用TheadPool.RegisterWaitForSingleObject 将阻塞调用推到线程池,这将在WaitHandle 发出信号时调用回调。

【讨论】:

    【解决方案2】:

    您可以在后台线程中调用 WaitAll,然后调用 BeginInvoke 以返回 UI 线程。

    【讨论】:

      【解决方案3】:

      看看ManualResetEvent。使用它你可以在你的线程完成时设置事件,并且任何其他线程可以等待这个事件,或者检查它是否处于信号状态。

      ManualResetEvent ev = new ManualReserEvent();
      while(Users["user428547"].AcceptanceRate == 0)
      {
         // this might take a long time
      };
      ev.Set(); // done, he accepted an answer.
      

      【讨论】:

        【解决方案4】:

        也许您可以自己启动另一个线程,并在该线程上自己调用WaitHandle.WaitAll?如果您没有启动太多其他线程,这应该可以正常工作。

        【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-29
        • 1970-01-01
        • 2018-02-16
        相关资源
        最近更新 更多