AutoResetEvent和ManualResetEvent之间的混合

时间:2011-09-28 14:42:52

标签: c# multithreading events

我想知道是否有任何混合EventWaitHandle将自动重置它的状态,因为当调用.Set()时AutoResetEvent正在执行,同时将允许每个执行.WaitOne()的人传递与ManualResetEvent相同的操作。

我提出的唯一一个解决方案是使用ManualResetEvent并执行以下操作非常难看:

event.Set();
Thread.Sleep(100);
event.Reset();

更好的方法是什么? 感谢。

UPD: Thansk和Hans我提出了以下解决方案。 看起来很有效:

class HybridWaitHandle
{

    private bool signal = false;
    private readonly object locker = new object();
    private int blocked = 0;

    void WaitOne()
    {
        lock (locker)
        {
            blocked++;

            while (!signal) Monitor.Wait(locker);

            blocked--;

            if (blocked == 0)
                signal = false;
        }
    }

    void Set()
    {
        lock (locker)
        {
            signal = true;
            Monitor.PulseAll(locker);
        }
    }

}

2 个答案:

答案 0 :(得分:2)

使用Monitor.PulseAll()代替。称为“有界缓冲区”,示例代码为is here。在.NET 4中可用作BlockingCollection<>。

答案 1 :(得分:1)

如果不了解更多关于你如何使用它的话,说起来有点难,但听起来像计数的信号量可能很适合这个问题。你释放信号量N次。这让N个线程运行。释放N个线程后,信号量将被重置。请注意,从技术上讲,这不一定是N个单独的线程 - 它可能是1次线程释放N次。

因此,如果您需要/想要确保释放N个单独的线程,您可能(对于一种可能性)想要创建2个单独的信号量,在这两个信号量的连续步骤之间交替。 N个线程在第一个信号量上等待。当您释放N次时,每个线程都会运行,然后等待其他信号量。最终所有线程将由第一个信号量释放并运行,这将重置该信号量。

然后,您可以使用其他信号量执行下一个处理步骤。

但是,请注意,大部分内容与线程的运行方式有些相反。你强迫所有线程保持锁定步骤,​​但如果你让它们尽可能“自由”地运行,它们通常会处于最佳状态。