title: A call to CancellationTokenSource.Cancel never returns
body: <p>I have a situation where a call to <code>CancellationTokenSource.Cancel</code> never returns. Instead, after <code>Cancel</code> is called (and before it returns) the execution continues with the cancellation code of the code that is being cancelled. If the code that is cancelled does not subsequently invoke any awaitable code then the caller that originally called <code>Cancel</code> never gets control back. This is very strange. I would expect <code>Cancel</code> to simply record the cancellation request and return immediately independent on the cancellation itself. The fact that the thread where <code>Cancel</code> is being called ends up executing code that belongs to the operation that is being cancelled and it does so before returning to the caller of <code>Cancel</code> looks like a bug in the framework. </p>
  
  <p>Here is how this goes:</p>
  
  <ol>
  <li><p>There is a piece of code, let’s call it “the worker code” that is waiting on some async code. To make things simple let’s say this code is awaiting on a Task.Delay:</p>
  
  <pre><code>try
  {
      await Task.Delay(5000, cancellationToken);
      // … 
  }
  catch (OperationCanceledException)
  {
      // ….
  }
  </code></pre></li>
  </ol>
  
  <p>Just before “the worker code” invokes <code>Task.Delay</code> it is executing on thread T1.
  The continuation (that is the line following the “await” or the block inside the catch) will be executed later on either T1 or maybe on some other thread depending on a series of factors.</p>
  
  <ol start="2">
  <li>There is another piece of code, let’s call it “the client code” that decides to cancel the <code>Task.Delay</code>. This code calls <code>cancellationToken.Cancel</code>. The call to <code>Cancel</code> is made on thread T2.</li>
  </ol>
  
  <p>I would expect thread T2 to continue by returning to the caller of <code>Cancel</code>. I also expect to see the content of <code>catch (OperationCanceledException)</code> executed very soon on thread T1 or on some thread other than T2.</p>
  
  <p>What happens next is surprising. I see that on thread T2, after <code>Cancel</code> is called, the execution continues immediately with the block inside <code>catch (OperationCanceledException)</code>. And that happens while the <code>Cancel</code> is still on the callstack. It is as if the call to <code>Cancel</code> is hijacked by the code that it is being cancelled. Here's a screenshot of Visual Studio showing this call stack:</p>
  
  <p><a href="https://i.stack.imgur.com/Uxmaq.png" rel="noreferrer"><img src="https://i.stack.imgur.com/Uxmaq.png" alt="Call stack"></a></p>
  
  <p><strong>More context</strong></p>
  
  <p>Here is some more context about what the actual code does:
  There is a “worker code” that accumulates requests. Requests are being submitted by some “client code”. Every few seconds “the worker code” processes these requests. The requests that are processed are eliminated from the queue. 
  Once in a while however, “the client code” decides that it reached a point where it wants requests to be processed immediately. To communicate this to “the worker code” it calls a method <code>Jolt</code> that “the worker code” provides. The method <code>Jolt</code> that is being called by “the client code” implements this feature by cancelling a <code>Task.Delay</code> that is executed by the worker’s code main loop. The worker’s code has its <code>Task.Delay</code> cancelled and proceeds to process the requests that were already queued.</p>
  
  <p>The actual code was stripped down to its simplest form and the code is <a href="https://github.com/ladimolnar/Samples/tree/master/Sources/AsyncIssue" rel="noreferrer">available on GitHub</a>.</p>
  
  <p><strong>Environment</strong></p>
  
  <p>The issue can be reproduced in console apps, background agents for Universal Apps for Windows and background agents for Universal Apps for Windows Phone 8.1.</p>
  
  <p>The issue cannot be reproduced in Universal apps for Windows where the code works as I would expect and the call to <code>Cancel</code> returns immediately.</p>