title: Cancelling BlockingCollection.GetConsumingEnumerable() and processing what's left
body: <p>I have one process generating work and a second process with a <code>BlockingCollection&lt;&gt;</code> that consumes that work. When I close my program, I need my consumer to stop <em>consuming</em> work, but I still need to quickly log the work that was pending but hadn't been consumed.</p>
  
  <p>Right now, my consumer spawns a thread that has a <code>foreach (&lt;object&gt; in BlockingCollection.GetConsumingEnumerable())</code> loop. When I stop my program, my producer calls <code>Consumer.BlockingCollection.CompleteAdding()</code>. What I find is that my consumer continues to process everything in the queue.</p>
  
  <p>Googling the issues tells me that I need to use a <code>CancellationToken</code>. So I tried that out:</p>
  
  <pre><code>private void Process () { // This method runs in a separate thread
      try {
          foreach (*work* in BlockingCollection.GetConsumingEnumerable(CancellationToken)) {
              // Consume
          }
      }
      catch (OperationCancelledException) {
          foreach (*work* in BlockingCollection.GetConsumingEnumerable()) {
              // quickly log
          }
      }
  }
  </code></pre>
  
  <p>My producer has:</p>
  
  <pre><code>private CancellationTokenSource StopFlag = new CancellationTokenSource ();
  MyConsumer.CancellationToken = StopFlag.Token;
  // Make the consumer spawn it's consuming thread...
  StopFlag.Cancel ();
  MyConsumer.BlockingCollection.CompleteAdding ();
  </code></pre>
  
  <p>When I try this, I get no indication that the OperationCancelledException ever happened.</p>
  
  <p><a href="https://stackoverflow.com/questions/9106419/how-to-cancel-getconsumingenumerable-on-blockingcollection">This question</a> tries to explain the use of a cancellation token, but it seems like it's not using it correctly. (Argument: if it works, then it's "correct enough".) And <a href="https://stackoverflow.com/questions/8001133/how-to-empty-a-blockingcollection">this question</a> would appear to be an exact duplicate of my question but with no example. (Same <a href="https://stackoverflow.com/questions/6512033/classic-producer-consumer-pattern-using-blockingcollection-and-tasks-net-4-tpl">here</a>.)</p>
  
  <p>So to reiterate: How do I properly use a <code>CancellationToken</code> on <code>BlockingCollection.GetConsumingEnumerable()</code> with the caveat that I need to process the remaining items in the queue after it gets cancelled using a different method?</p>
  
  <p>(I think my problem is centered around the proper use of the CancellationToken. None of my testing indicates that the process is actually being cancelled. (<code>StopFlag.IsCancellationRequested</code> always equals <code>false</code>.))</p>