代码之家  ›  专栏  ›  技术社区  ›  kosnkov

C#线程,WaitHandle.WaitAll

  •  2
  • kosnkov  · 技术社区  · 14 年前

    这是否可能不使用WaitHandle.WaitAll(waitHandles)阻止winForm,而只是设置另一个线程,该线程将在从WaitHandle.WaitAll获取投诉信号时触发?

    4 回复  |  直到 14 年前
        1
  •  3
  •   Brian Gideon    14 年前

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

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

    相反,我通常使用 CountdownEvent 当我想等待多个事件时初始化。现在,你会遇到的问题是它仍然需要你打电话 Wait 在一些你正试图避免的线索上。避免进行阻塞调用的标准机制是使用 ThreadPool.RegisterWaitForSingleObject 方法。但不幸的是 等待手柄 倒计时事件 不是从那个类继承的。

    解决方法是创建自己的 CountdownWaitHandle 类中可以使用的 ThreadPool.RegisterWaitForSingleObject 方法。此方法将允许您指定一个回调委托,该委托将在 等待手柄 是有信号的。

    下面是 倒数等待句柄 上课。你必须自己添加所有必要的harding代码,但这将使你开始。

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

    这里的想法是不要使用很多不同的 等待手柄 使用单个实例 倒数等待句柄 实例。使用所需的计数初始化实例,然后调用 Signal 减少计数。一旦数到零 等待手柄 将进入信号状态。所以不要打电话 Set 关于多重 等待手柄 实例和阻塞 WaitHandle.WaitAll等待 你现在打电话来 信号 在这个实例上,通过调用 WaitOne . 同样,您可以使用 TheadPool.RegisterWaitForSingleObject 等待手柄 是有信号的。

        2
  •  0
  •   SLaks    14 年前

    你可以打电话 WaitAll 在后台线程中,然后调用 BeginInvoke 返回到UI线程。

        3
  •  0
  •   Moo-Juice    14 年前

    看一看 ManualResetEvent . 使用此选项,可以在线程完成时设置事件,任何其他线程都可以等待此事件,或者检查它是否处于信号状态。

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

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