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() 呼び出しの実行でビジー状態になると、Pulse が失われます。

しかし、それは問題である必要はありません。Enqueue() のたびにパルスが発生し、基本的にパルスが必要になるのは queue.Count が 0 から 1 になったときだけです。さらに多くのパルスが必要になります。

しかし、パルスの数を最適化しようとすると、おそらく問題が発生します。Wait/Pulse がステートレスであるという事実は、慎重に使用する必要があることを意味します。

于 2012-08-02T13:54:39.483 に答える