title: How to implement an efficient WhenEach that streams an IAsyncEnumerable of task results?
body: <p>I am trying to update my toolset with the new tools offered by <a href="https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8" rel="nofollow noreferrer">C# 8</a>, and one method that seems particularly useful is a version of <a href="https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.whenall" rel="nofollow noreferrer"><code>Task.WhenAll</code></a> that returns an <a href="https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.iasyncenumerable-1" rel="nofollow noreferrer"><code>IAsyncEnumerable</code></a>. This method should stream the task results as soon as they become available, so naming it <code>WhenAll</code> doesn't make much sense. <code>WhenEach</code> sounds more appropriate. The signature of the method is:</p>
  <pre><code>public static IAsyncEnumerable&lt;TResult&gt; WhenEach&lt;TResult&gt;(Task&lt;TResult&gt;[] tasks);
  </code></pre>
  <p>This method could be used like this:</p>
  <pre><code>var tasks = new Task&lt;int&gt;[]
  {
      ProcessAsync(1, 300),
      ProcessAsync(2, 500),
      ProcessAsync(3, 400),
      ProcessAsync(4, 200),
      ProcessAsync(5, 100),
  };
  
  await foreach (int result in WhenEach(tasks))
  {
      Console.WriteLine($&quot;Processed: {result}&quot;);
  }
  
  static async Task&lt;int&gt; ProcessAsync(int result, int delay)
  {
      await Task.Delay(delay);
      return result;
  }
  </code></pre>
  <p>Expected output:</p>
  <blockquote>
  <p>Processed: 5<br />
  Processed: 4<br />
  Processed: 1<br />
  Processed: 3<br />
  Processed: 2</p>
  </blockquote>
  <p>I managed to write a basic implementation using the method <a href="https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.whenany" rel="nofollow noreferrer"><code>Task.WhenAny</code></a> in a loop, but there is a problem with this approach:</p>
  <pre><code>public static async IAsyncEnumerable&lt;TResult&gt; WhenEach&lt;TResult&gt;(
      Task&lt;TResult&gt;[] tasks)
  {
      var hashSet = new HashSet&lt;Task&lt;TResult&gt;&gt;(tasks);
      while (hashSet.Count &gt; 0)
      {
          var task = await Task.WhenAny(hashSet).ConfigureAwait(false);
          yield return await task.ConfigureAwait(false);
          hashSet.Remove(task);
      }
  }
  </code></pre>
  <p>The problem is the performance. The <code>Task.WhenAny</code> method has to watch for the completion of all the supplied tasks, and it does so by attaching and detaching continuations, so calling it repeatedly in a loop results in O(n²) computational complexity. My naive implementation struggles to process 10,000 tasks. The overhead is nearly 10 sec in my machine. I would like the method to be nearly as performant as the build-in <code>Task.WhenAll</code>, that can handle hundreds of thousands of tasks with ease. How could I improve the <code>WhenEach</code> method to make it perform decently?</p>