2

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

主要的 :

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...");
    }

}

班级 :

   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. 

现在 ?两个线程都忙!

知道脉搏会丢失(或不会?)

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

4

1 回答 1

3

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

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

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

但是,当您尝试优化脉冲数时,您可能会遇到麻烦。Wait/Pulse 是无状态的这一事实确实意味着您应该谨慎使用它。

于 2012-08-02T13:54:39.483 回答