title: How to force an IAsyncEnumerable to respect a CancellationToken
body: <p>I have an async iterator method that produces an <a href="https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.iasyncenumerable-1" rel="nofollow noreferrer"><code>IAsyncEnumerable&lt;int&gt;</code></a> (a stream of numbers), one number every 200 msec. The caller of this method consumes the stream, but wants to stop the enumeration after 1000 msec. So a <code>CancellationTokenSource</code> is used, and the token is passed as
  an argument to the <a href="https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.taskasyncenumerableextensions.withcancellation" rel="nofollow noreferrer"><code>WithCancellation</code></a> extension method. But the token is not respected. The enumeration continues until all the numbers are consumed:</p>
  <pre><code>static async IAsyncEnumerable&lt;int&gt; GetSequence()
  {
      for (int i = 1; i &lt;= 10; i++)
      {
          await Task.Delay(200);
          yield return i;
      }
  }
  
  var cts = new CancellationTokenSource(1000);
  await foreach (var i in GetSequence().WithCancellation(cts.Token))
  {
      Console.WriteLine($&quot;{DateTime.Now:HH:mm:ss.fff} &gt; {i}&quot;);
  }
  </code></pre>
  <p>Output:</p>
  <blockquote>
  <p>12:55:17.506 &gt; 1<br />
  12:55:17.739 &gt; 2<br />
  12:55:17.941 &gt; 3<br />
  12:55:18.155 &gt; 4<br />
  12:55:18.367 &gt; 5<br />
  12:55:18.570 &gt; 6<br />
  12:55:18.772 &gt; 7<br />
  12:55:18.973 &gt; 8<br />
  12:55:19.174 &gt; 9<br />
  12:55:19.376 &gt; 10</p>
  </blockquote>
  <p>The expected output is a <code>TaskCanceledException</code> to occur after number 5. It seems that I have misunderstood what the <code>WithCancellation</code> is actually doing. The method just passes the supplied token to the iterator method, if that method accepts one. Otherwise, like with the method <code>GetSequence()</code> in my example, the token is ignored. I suppose that the solution in my case is to interrogate manually the token inside the body of the enumeration:</p>
  <pre><code>var cts = new CancellationTokenSource(1000);
  await foreach (var i in GetSequence())
  {
      cts.Token.ThrowIfCancellationRequested();
      Console.WriteLine($&quot;{DateTime.Now:HH:mm:ss.fff} &gt; {i}&quot;);
  }
  </code></pre>
  <p>This is simple and works well. But in any case I wonder if it would be possible to create an extension method that does what I expected the <code>WithCancellation</code> to do, to bake the token inside the ensuing enumeration. This is the signature of the needed method:</p>
  <pre><code>public static IAsyncEnumerable&lt;T&gt; WithEnforcedCancellation&lt;T&gt;(
      this IAsyncEnumerable&lt;T&gt; source, CancellationToken cancellationToken)
  {
      // Is it possible?
  }
  </code></pre>