title: How to cancel Task but wait until it finishes?
body: <p>I have threaded task wich performs some operation in loop:</p>
  
  <pre><code>static void TaskAction(CancellationToken ct)
  {
      while (SomeCondition())
      {
          DoSomeSeriousJob();
          ct.ThrowIfCancellationRequested();
      }
  }
  
  static void DoSomeSeriousJob()
  {
      Console.WriteLine("Serious job started");
      Thread.Sleep(5000);
      Console.WriteLine("Serious job done");
  }
  </code></pre>
  
  <p>I start it and then cancel after some period of time:</p>
  
  <pre><code>    var cts = new CancellationTokenSource();
      var task = Task.Factory.StartNew(() =&gt; TaskAction(cts.Token), cts.Token);
      Thread.Sleep(1000);
      cts.Cancel();
  </code></pre>
  
  <p>This operation must be finished correctly, I don't want to interrupt it. But I want to send a cancellation request to my task <strong>and wait until it finishes</strong> correctly (by which I mean it gets to some point in code).
  I tryed following approaches:</p>
  
  <h3>1. Wait(CancellationToken ct)</h3>
  
  <pre><code>try
  {
      task.Wait(cts.Token);
  }
  catch (OperationCanceledException)
  {
      Console.WriteLine("Task cancelled");
  }
  // Must be joined here.
  </code></pre>
  
  <p>In this case program returns immediately from <code>Wait()</code>. The task continues to run until <code>ThrowIfCancellationRequested()</code> but if main thread exits the task gets interrupted too.</p>
  
  <h3>2. Wait()</h3>
  
  <pre><code>try
  {
      task.Wait();
  }
  catch (OperationCanceledException)
  {
      Console.WriteLine("Task cancelled");
  }
  catch (Exception ex)
  {
      Console.WriteLine(ex.ToString());
  }
  </code></pre>
  
  <p>Here main thread waits for completion but at the end <code>AggregateException</code> is risen with <code>InnerException</code> = <code>TaskCancelledException</code> (not <code>OperationCancelledException</code>).</p>
  
  <h3>3. Check IsCancellationRequested() and no exceptions</h3>
  
  <pre><code>static void TaskAction(CancellationToken ct)
  {
      while (SomeCondition())
      {
          DoSomeSeriousJob();
          if (ct.IsCancellationRequested)
              break;
      }
  }
  // ...
  task.Wait();
  </code></pre>
  
  <p>In this case no exceptions are risen but the task gets status <code>RanToCompletion</code> in the end. This is not distiguishable from correct completion when <code>SomeCodition()</code> starts to return false.</p>
  
  <p>All these problem have easy workarounds but I wonder, may be I'm missing something? Could anybody advise me better solution?</p>