title: Why isn't Task.WhenAll working?
body: <p>Here's some code I'm working with, that fires of three tasks. My Stop is called, and from the output, it looks as though the tasks finish <em>after</em> Stop returns, which isn't what I'd expect.</p>
  
  <p>This is Visual Studio 2013 with .NET 4.5.1</p>
  
  <p>I tried the same using AutoResetEvent which worked as expected.</p>
  
  <p>Here's the output from this:</p>
  
  <pre><code>Three tasks without auto reset
  Starting...
  FIRST
  SECOND
  THIRD
  Running...
  FIRST
  FIRST
  FIRST
  SECOND
  FIRST
  FIRST
  THIRD
  ...
  SECOND
  FIRST
  Stopping...
  THIRD
  All done!
  First done
  Second done
  Third done
  </code></pre>
  
  <p>What I'd expect to see is:</p>
  
  <pre><code>First done
  Second done
  Third done
  All done!
  </code></pre>
  
  <p>Here's the code (I even added locking around the Console output, but it made no difference):</p>
  
  <pre><code>public class ThreeTasksWithoutAutoResetEvent
  {
      private CancellationTokenSource cancellation;
  
      private Task[] tasks;
  
      private object obj = new object();
  
      public ThreeTasksWithoutAutoResetEvent()
      {
          Console.WriteLine("Three tasks without auto reset");
  
          cancellation = new CancellationTokenSource();
  
          tasks = new Task[3];
  
          Message("Starting...");
  
          Start();
  
          Message("Running...");
  
          Thread.Sleep(3000);
  
          Message("Stopping...");
  
          Stop();
  
          Message("All done!");
      }
  
      private void Start()
      {
          tasks[0] = this.First(cancellation.Token);
          tasks[1] = this.Second(cancellation.Token);
          tasks[2] = this.Third(cancellation.Token);
      }
  
      private async void Stop()
      {
          cancellation.Cancel();
  
          await Task.WhenAll(tasks);
      }
  
      private async Task First(CancellationToken token)
      {
          await Task.Run(
              () =&gt;
              {
                  while (!token.IsCancellationRequested)
                  {
                      Message("FIRST");
                      Thread.Sleep(100);
                  }
  
                  Message("First done");
              }, token);
      }
  
      private async Task Second(CancellationToken token)
      {
          await Task.Run(
              () =&gt;
              {
                  while (!token.IsCancellationRequested)
                  {
                      Message("SECOND");
                      Thread.Sleep(300);
                  }
  
                  Message("Second done");
              }, token);
      }
  
      private async Task Third(CancellationToken token)
      {
          await Task.Run(
              () =&gt;
              {
                  while (!token.IsCancellationRequested)
                  {
                      Message("THIRD");
                      Thread.Sleep(500);
                  }
  
                  Message("Third done");
              }, token);
      }
  
      private void Message(string message)
      {
          lock (obj)
          {
              Console.WriteLine(message);
          }
      }
  }
  </code></pre>