title: What's the diference between Task.WhenAll() and foreach(var task in tasks)
body: <p>After a few hours of struggle I found a bug in my app. I considered the 2 functions below to have identical behavior, but it turned out they don't.</p>
  
  <p>Can anyone tell me what's really going on under the hood, and why they behave in a different way?</p>
  
  <pre><code>public async Task MyFunction1(IEnumerable&lt;Task&gt; tasks){
      await Task.WhenAll(tasks);
  
      Console.WriteLine("all done"); // happens AFTER all tasks are finished
  }
  
  public async Task MyFunction2(IEnumerable&lt;Task&gt; tasks){
      foreach(var task in tasks){
          await task;
      }
  
      Console.WriteLine("all done"); // happens BEFORE all tasks are finished
  }
  </code></pre>