Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>The whole idea behind <code>Parallel.ForEach()</code> is that you have a set of threads and each thread processes part of the collection. As you noticed, this doesn't work with <code>async</code>-<code>await</code>, where you want to release the thread for the duration of the async call. </p> <p>You could “fix” that by blocking the <code>ForEach()</code> threads, but that defeats the whole point of <code>async</code>-<code>await</code>.</p> <p>What you could do is to use <a href="http://msdn.microsoft.com/en-us/library/hh228603.aspx" rel="noreferrer">TPL Dataflow</a> instead of <code>Parallel.ForEach()</code>, which supports asynchronous <code>Task</code>s well.</p> <p>Specifically, your code could be written using a <code>TransformBlock</code> that transforms each id into a <code>Customer</code> using the <code>async</code> lambda. This block can be configured to execute in parallel. You would link that block to an <code>ActionBlock</code> that writes each <code>Customer</code> to the console. After you set up the block network, you can <code>Post()</code> each id to the <code>TransformBlock</code>.</p> <p>In code:</p> <pre><code>var ids = new List&lt;string&gt; { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" }; var getCustomerBlock = new TransformBlock&lt;string, Customer&gt;( async i =&gt; { ICustomerRepo repo = new CustomerRepo(); return await repo.GetCustomer(i); }, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded }); var writeCustomerBlock = new ActionBlock&lt;Customer&gt;(c =&gt; Console.WriteLine(c.ID)); getCustomerBlock.LinkTo( writeCustomerBlock, new DataflowLinkOptions { PropagateCompletion = true }); foreach (var id in ids) getCustomerBlock.Post(id); getCustomerBlock.Complete(); writeCustomerBlock.Completion.Wait(); </code></pre> <p>Although you probably want to limit the parallelism of the <code>TransformBlock</code> to some small constant. Also, you could limit the capacity of the <code>TransformBlock</code> and add the items to it asynchronously using <code>SendAsync()</code>, for example if the collection is too big.</p> <p>As an added benefit when compared to your code (if it worked) is that the writing will start as soon as a single item is finished, and not wait until all of the processing is finished.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload