title: Canceling a Parallel.ForEach
body: <p>From <a href="https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/how-to-cancel-a-parallel-for-or-foreach-loop" rel="nofollow noreferrer">Microsoft documentation</a>, I have this piece of code. But it doesn't work as intended. The loop stops without hiting the cancellation key when it's finish. No key press or console.write in the new task is displayed. </p>
  
  <p>Console ouput, debug trace explainned:</p>
  
  <pre class="lang-none prettyprint-override"><code>Press any key to start. Press 'c' to cancel.    &lt;-- Starting
  .                                               &lt;-- Key pressed
  
  &lt;Multiple line of result&gt;                       &lt;-- Parallel.ForEach ouput
  (...)
  &lt;/Multiple line of result&gt;
  
  Canceled                                        &lt;-- Hit finally Parallel.ForEach over
  END! Press a key                                &lt;-- Program
  </code></pre>
  
  <p>What I expected was: Starting a thread waiting for a specific key. If anything else than this specific key is hit, prompt for specific. </p>
  
  <p>What I did:</p>
  
  <pre><code>static void Main(string[] args)
  {
      test();
  }
  static void test()
  {
      int[] nums = Enumerable.Range(0, 1000).ToArray();
      CancellationTokenSource cts = new CancellationTokenSource();
  
      // Use ParallelOptions instance to store the CancellationToken
      ParallelOptions po = new ParallelOptions();
      po.CancellationToken = cts.Token;
      po.MaxDegreeOfParallelism = System.Environment.ProcessorCount;
      po.CancellationToken.ThrowIfCancellationRequested();
      Console.WriteLine("Press any key to start. Press 'c' to cancel.");
      Console.ReadKey();
  
      // Run a task so that we can cancel from another thread.
      Task.Factory.StartNew(() =&gt;
      {
          while (Console.KeyAvailable)
          {
              if (Console.ReadKey().KeyChar == 'c')
              {
                  Console.WriteLine("Cancellation..");
                  cts.Cancel();
              }
              Console.WriteLine("\nPress 'c' to cancel.");
          }
          Console.WriteLine("task ..");
      });
  
      try
      {
          Parallel.ForEach(nums, po, (num) =&gt;
          {
              double d = Math.Sqrt(num);
              Console.WriteLine("{0} on {1}", d, Thread.CurrentThread.ManagedThreadId);
  
          });
      }
      catch (OperationCanceledException e)
      {
          Console.WriteLine(e.Message);
      }
      catch (Exception e)
      {  // perhaps an exception that was not expected? 
          Console.WriteLine(e.Message);
      }
      finally
      {
          cts.Dispose();
          Console.WriteLine("Canceled");
      }
  
      Console.WriteLine("END! Press a key");
      Console.ReadKey();
  }
  </code></pre>
  
  <p>99% msdn code, minor edit for trace, trying to debug. </p>