Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>In the case where you need to preserve order from your <code>IEnumerable&lt;T&gt;</code>, you'll likely want to <a href="http://msdn.microsoft.com/en-us/library/dd997411.aspx" rel="nofollow">implement a custom partitioner</a> of the <a href="http://msdn.microsoft.com/en-us/library/dd394988.aspx" rel="nofollow"><code>OrderablePartitioner&lt;T&gt;</code></a> variety. The example code for this class includes a simple example which retrieves them one at a time from the enumeration in increasing order.</p> <p>However, this is a lot of work for something which could be a simple producer-consumer model with something like <a href="http://msdn.microsoft.com/en-us/library/dd267265.aspx" rel="nofollow"><code>ConcurrentQueue&lt;T&gt;</code></a>:</p> <pre><code>var queue = new ConcurrentQueue&lt;X&gt;(yourEnumerableOfX); Action consumer = () =&gt; { X x; while (queue.TryDequeue(out x)) { x.Frob(); } }; // At most N "in flight" int maxParallelism = Environment.ProcessorCount; var consumers = Enumerable.Repeat(consumer, maxParallelism).ToArray(); Parallel.Invoke(consumers); </code></pre> <p>Using this code you'll be guaranteed First-In-First-Out behavior, and that your requests end up processed "in flight" nearly in the order they are received. Once placed in parallel, you'll have no guarantee they stay in sequential order.</p> <p>Alternatively, you can use the following (with the restriction that the number of queue items stays fixed):</p> <pre><code>// Executes exactly queue.Count iterations at the time of Parallel.ForEach // due to "snapshot" isolation of ConcurrentQueue&lt;X&gt;.GetEnumerator() var queue = new ConcurrentQueue&lt;X&gt;(yourEnumerableOfX); Parallel.ForEach( queue, _ =&gt; { X x; if (queue.TryDequeue(out x)) { x.Frob(); } }); </code></pre> <p>If you would like to keep on producing in one thread, and consuming in others use a <a href="http://msdn.microsoft.com/en-us/library/dd997371.aspx" rel="nofollow"><code>BlockingCollection&lt;T&gt;</code></a> with a queue as its backing collection:</p> <pre><code>var queue = new BlockingCollection&lt;X&gt;(new ConcurrentQueue&lt;X&gt;()); // add to it Task.Factory.StartNew( () =&gt; { foreach (var x in yourEnumerableOfX) { queue.Add(x); Thread.Sleep(200); } // Signal to our consumers we're done: queue.CompleteAdding(); }); </code></pre> <p>Now we need 'unbounded' consumers since we are unsure exactly how many queue items may be present:</p> <pre><code>// Roughly the same consumer code as above, but 'unbounded' Action consumer = () =&gt; { while (!queue.IsCompleted) { X x; try { // blocking form, switch to TryTake and maybe Thread.Sleep() x = queue.Take(); } catch (InvalidOperationException) { // none left break; } x.Frob(); } }; int maxParallelism = Environment.ProcessorCount; var consumers = Enumerable.Repeat(consumer, maxParallelism).ToArray(); Parallel.Invoke(consumers); </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

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