Monitor.Wait需要同步吗?

use*_*631 7 c# synchronization monitor producer-consumer

我已经开发了一个通用的生产者 - 消费者队列,它由Monitor以下列方式产生脉冲:

入队:

    public void EnqueueTask(T task)
    {
        _workerQueue.Enqueue(task);
        Monitor.Pulse(_locker);
    }
Run Code Online (Sandbox Code Playgroud)

出队:

private T Dequeue()
    {
        T dequeueItem;
        if (_workerQueue.Count > 0)
        {
               _workerQueue.TryDequeue(out dequeueItem);
            if(dequeueItem!=null)
                return dequeueItem;
        }
        while (_workerQueue.Count == 0)
            {
                Monitor.Wait(_locker);
        }
         _workerQueue.TryDequeue(out dequeueItem);
        return dequeueItem;
    }
Run Code Online (Sandbox Code Playgroud)

wait部分产生以下SynchronizationLockException:"从一个不同步的代码块中调用了对象同步方法"我是否需要同步它?为什么?使用ManualResetEvents还是Slim版本的.NET 4.0会更好吗?

Jon*_*eet 6

是的,当前线程需要"拥有"监视器以便调用Wait或者Pulse,如文档所述.(所以你也需要锁定Pulse.)我不知道为什么需要它的细节,但它在Java中是相同的.我通常发现我还是想要这样做,以使调用代码干净.

请注意,Wait释放监视器本身,然后等待Pulse,然后在返回之前重新获取监视器.

至于使用ManualResetEventAutoResetEvent代替 - 你可以,但我个人更喜欢使用这些Monitor方法,除非我需要等待句柄的其他一些功能(例如原子等待任何/所有多个句柄).