Monitor.Pulse失去信号?

时间:2012-08-02 13:37:57

标签: c# .net multithreading monitor

我有这个生产者/消费者代码:

主要:

static void Main()
{
    using(PCQueue q = new PCQueue(2))
    {
        for(int i = 0; i < 10; i++)
        {
            int itemNumber = i; // To avoid the captured variable trap
            q.EnqueueItem(() = > {
                Thread.Sleep(1000); // Simulate time-consuming work
                Console.Write(" Task" + itemNumber);
            });
        }
        Console.WriteLine("Enqueued 10 items");
        Console.WriteLine("Waiting for items to complete...");
    }

}

CLASS:

   public class PCQueue: IDisposable
  {
      readonly object _locker = new object();
      Thread[] _workers;
      Queue < Action > _itemQ = new Queue < Action > ();
      public PCQueue(int workerCount)
      {
          _workers = new Thread[workerCount];
          // Create and start a separate thread for each worker
          for(int i = 0; i < workerCount; i++)
          (_workers[i] = new Thread(Consume)).Start();
      }
      public void Dispose()
      {
          // Enqueue one null item per worker to make each exit.
          foreach(Thread worker in _workers) EnqueueItem(null);
      }
      public void EnqueueItem(Action item)
      {
          lock(_locker)
          {
              _itemQ.Enqueue(item); // We must pulse because we're
              Monitor.Pulse(_locker); // changing a blocking condition.
          }
      }
      void Consume()
      {
          while(true) // Keep consuming until
          { // told otherwise.
              Action item;
              lock(_locker)
              {
                  while(_itemQ.Count == 0) Monitor.Wait(_locker);
                  item = _itemQ.Dequeue();
              }
              if(item == null) return; // This signals our exit.
              item(); // Execute item.
          }
      }
  }

问题:

让我们说执行item();需要很长时间。

1) we enqueue a new work and pulse. ( 1 consumer is busy now)
2) we enqueue a new work and pulse. ( second consumer is busy now)
3) we enqueue a new work and pulse. 

现在?两个线程都很忙!

know 脉搏会丢失(或不会?)

唯一的解决方案是将其更改为AutoResetEvent吗?

1 个答案:

答案 0 :(得分:3)

  

现在?两个线程都很忙!   我知道脉冲会丢失(或不会?)

是的,当(所有)线程忙于执行Item()调用时,Pulse将丢失。

但这不一定是个问题,你在每个Enqueue()之后都是Pulsing,并且只有当queue.Count从0变为1时才需要Pulse。你需要更多的脉冲。

但是当你试图优化脉冲数时,你可能会遇到麻烦。 Wait / Pulse无状态的事实意味着你应该小心使用它。