title: C# making concurrent executing asynchronous
body: <p>I'm currently trying to improve my understanding of Multithreading and the TPL in particular.
  A lot of the constructs make complete sense and I can see how they improve scalability / execution speed.</p>
  
  <p>I know that for asynchronous calls that don't tie up a thread (like I/O bound calls), Task.WhenAll would be the perfect fit.
  One thing I am wondering about, though, is the best practice for making CPU-bound work that I want to run in parallel asynchronous.</p>
  
  <p>To make code run in parallel the obvious choice would be the Parallel class.
  As an example, say I have an array of data I want to perform some number crunching on:</p>
  
  <pre><code>string[] arr = { "SomeData", "SomeMoreData", "SomeOtherData" };
  Parallel.ForEach(arr, (s) =&gt;
  {
      SomeReallyLongRunningMethod(s);
  });
  </code></pre>
  
  <p>This would run in parallel (if the analyser decides that parallel is faster than synchronous), but it would also block the thread.</p>
  
  <p>Now the first thing that came to my mind was simply wrapping it all in Task.Run() ala:</p>
  
  <pre><code>string[] arr = { "SomeData", "SomeMoreData", "SomeOtherData" };
  await Task.Run(() =&gt; Parallel.ForEach(arr, (s) =&gt;
  {
      SomeReallyLongRunningMethod(s);
  }));
  </code></pre>
  
  <p>Another option would be to either have a seperate Task returing method or inline it and use Task.WhenAll like so:</p>
  
  <pre><code>static async Task SomeReallyLongRunningMethodAsync(string s)
  {
      await Task.Run(() =&gt;
      {
          //work...
      });
  }
  // ...
  await Task.WhenAll(arr.Select(s =&gt; SomeReallyLongRunningMethodAsync(s)));
  </code></pre>
  
  <p>The way I understand it is that option 1 creates a whole Task that will, for the life of it, tie up a thread to just sit there and wait until the Parallel.ForEach finishes.
  Option 2 uses Task.WhenAll (for which I don't know whether it ties up a thread or not) to await all Tasks, but the Tasks had to be created manually. Some of my resources (expecially MS ExamRef 70-483) have explicitly advised against manually creating Tasks for CPU-bound work as the Parallel class is supposed to be used for it.</p>
  
  <p>Now I'm left wondering about the best performing version / best practice for the problem of wanting parallel execution that can be awaited.
  I hope some more experienced programmer can shed some light on this for me!</p>