title: Threadsafe FIFO Queue/Buffer
body: <p>I need to implement a sort of task buffer. Basic requirements are:</p>
  
  <ul>
  <li>Process tasks in a single background thread</li>
  <li>Receive tasks from multiple threads</li>
  <li>Process ALL received tasks i.e. make sure buffer is drained of buffered tasks after a stop signal is received</li>
  <li>Order of tasks received per thread must be maintained</li>
  </ul>
  
  <p>I was thinking of implementing it using a Queue like below. Would appreciate feedback on the implementation. Are there any other brighter ideas to implement such a thing?</p>
  
  <pre><code>public class TestBuffer
  {
      private readonly object queueLock = new object();
      private Queue&lt;Task&gt; queue = new Queue&lt;Task&gt;();
      private bool running = false;
  
      public TestBuffer()
      {
      }
  
      public void start()
      {
          Thread t = new Thread(new ThreadStart(run));
          t.Start();
      }
  
      private void run()
      {
          running = true;
  
          bool run = true;
          while(run)
          {
              Task task = null;
              // Lock queue before doing anything
              lock (queueLock)
              {
                  // If the queue is currently empty and it is still running
                  // we need to wait until we're told something changed
                  if (queue.Count == 0 &amp;&amp; running)
                  {
                      Monitor.Wait(queueLock);
                  }
  
                  // Check there is something in the queue
                  // Note - there might not be anything in the queue if we were waiting for something to change and the queue was stopped
                  if (queue.Count &gt; 0)
                  {
                      task = queue.Dequeue();
                  }
              }
  
              // If something was dequeued, handle it
              if (task != null)
              {
                  handle(task);
              }
  
              // Lock the queue again and check whether we need to run again
              // Note - Make sure we drain the queue even if we are told to stop before it is emtpy
              lock (queueLock)
              {
                  run = queue.Count &gt; 0 || running;
              }
          }
      }
  
      public void enqueue(Task toEnqueue)
      {
          lock (queueLock)
          {
              queue.Enqueue(toEnqueue);
              Monitor.PulseAll(queueLock);
          }
      }
  
      public void stop()
      {
          lock (queueLock)
          {
              running = false;
              Monitor.PulseAll(queueLock);
          }
      }
  
      public void handle(Task dequeued)
      {
          dequeued.execute();
      }
  }
  </code></pre>