1  using System;
   2  using System.Collections.Generic;
   3  using System.Threading;
   4  
   5  /*
   6  Create N worker threads. Each thread waits for work.
   7  doWork() allows each thread to stop waiting.  
   8  When a worker thread has completed a task, it sets its
   9  workIsDoneEvent_.  The Distributor waits for all worker threads
  10  to be done with their tasks before doWork() returns.
  11   
  12  When a client invokes requestWorkerTermination(), the 
  13  terminateThreads_ bit is set, and doWork() is invoked.
  14  This time, each worker skips its work, but still sets its
  15  workIsDoneEvent_, and then terminates.
  16  */
  17  
  18  class Distributor {  // Distribute work among multiple threads
  19      protected Distributor() {
  20          for(uint k = 0; k<numberOfThreads_; k++) {
  21              WorkerThread workerThread = new WorkerThread(k, this);
  22              workerThread_.Add(workerThread);
  23              workIsDoneEvents_[k] = workerThread.getWorkIsDoneEvent();
  24              Thread thread = new Thread(new ThreadStart(workerThread.doWork));
  25              thread.Start(); 
  26              }
  27          }
  28  
  29      public void doWork() {
  30          foreach (WorkerThread workerThread in workerThread_) workerThread.requestWork();
  31          WaitHandle.WaitAll(workIsDoneEvents_);
  32          }
  33  
  34      // Executed in worker threads:
  35      public void doWork(uint workerNumber) {work_.execute(workerNumber);}
  36  
  37      public void requestWorkerTermination() {
  38          terminateThreads_ = true;
  39          doWork();
  40          }
  41  
  42      public bool terminateThreads() {return terminateThreads_;}
  43  
  44      public void set(Work work) {work_ = work;}
  45  
  46      private Work work_;
  47  
  48      private List<WorkerThread> workerThread_ = new List<WorkerThread>();
  49      private WaitHandle[] workIsDoneEvents_ = new WaitHandle[numberOfThreads_];
  50      private bool terminateThreads_ = false;
  51  
  52      public static readonly uint numberOfThreads_ = (uint)Environment.ProcessorCount;
  53  }
  54  
  55  interface Work {  // Executed in worker threads:
  56      void execute(uint workerNumber);
  57  }