<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Parallel Programming with .NET : ThreadPool</title><link>http://blogs.msdn.com/pfxteam/archive/tags/ThreadPool/default.aspx</link><description>Tags: ThreadPool</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>PDC09 Parallelism Session Videos Now Available</title><link>http://blogs.msdn.com/pfxteam/archive/2009/11/21/9926691.aspx</link><pubDate>Sat, 21 Nov 2009 09:05:20 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9926691</guid><dc:creator>toub</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/pfxteam/comments/9926691.aspx</comments><wfw:commentRss>http://blogs.msdn.com/pfxteam/commentrss.aspx?PostID=9926691</wfw:commentRss><wfw:comment>http://blogs.msdn.com/pfxteam/rsscomments.aspx?PostID=9926691</wfw:comment><description>&lt;p&gt;Attendees at PDC09 this past week were privy to quite a few sessions on parallel computing.&amp;#160; Now that the videos of these sessions are online, you can view them as well from the comfort of your own home.&amp;#160; Here are some of the key parallelism-related sessions from this past week:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Overview&lt;/strong&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://ecn.channel9.msdn.com/o9/pdc09/wmvhigh/FT07.wmv"&gt;The State of Parallel Programming&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&amp;#160;&lt;strong&gt;Managed code in Visual Studio 2010&lt;/strong&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://ecn.channel9.msdn.com/o9/pdc09/wmvhigh/FT03.wmv"&gt;Manycore and .NET 4: A Match Made in Visual Studio 2010&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://ecn.channel9.msdn.com/o9/pdc09/wmvhigh/FT21.wmv"&gt;PLINQ: LINQ, but Faster!&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://ecn.channel9.msdn.com/o9/pdc09/wmvhigh/FT20.wmv"&gt;F# for Parallel and Asynchronous Programming&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;strong&gt;Native code in Visual Studio 2010&lt;/strong&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://ecn.channel9.msdn.com/o9/pdc09/wmvhigh/FT19.wmv"&gt;C++ Forever: Interactive Applications in the Age of Manycore&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://ecn.channel9.msdn.com/o9/pdc09/wmvhigh/SVR10.wmv"&gt;Lighting up Windows Server 2008 R2 Using the ConcRT on UMS&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://ecn.channel9.msdn.com/o9/pdc09/wmvhigh/SVR18.wmv"&gt;Developing Applications for Scale-Up Servers Running Windows Server 2008 R2&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;strong&gt;HPC Server&lt;/strong&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://ecn.channel9.msdn.com/o9/pdc09/wmvhigh/SVR01.wmv"&gt;Accelerating Applications Using Windows HPC Server 2008&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;strong&gt;Research and Incubation&lt;/strong&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://ecn.channel9.msdn.com/o9/pdc09/wmvhigh/VTL02.wmv"&gt;Axum: A .NET Language for Safe and Scalable Concurrency&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://ecn.channel9.msdn.com/o9/pdc09/wmvhigh/VTL32.wmv"&gt;Concurrency Fuzzing &amp;amp; Data Races&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://ecn.channel9.msdn.com/o9/pdc09/wmvhigh/SVR17.wmv"&gt;Data-Intensive Computing on Windows HPC Server with DryadLINQ&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://ecn.channel9.msdn.com/o9/pdc09/wmvhigh/VTL04.wmv"&gt;Rx: Reactive Extensions for .NET&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://ecn.channel9.msdn.com/o9/pdc09/wmvhigh/FT36.wmv"&gt;Future of Garbage Collection&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://ecn.channel9.msdn.com/o9/pdc09/wmvhigh/FT11.wmv"&gt;Future Directions for C# and Visual Basic&lt;/a&gt;&amp;#160;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Enjoy!&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9926691" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/pfxteam/archive/tags/ThreadPool/default.aspx">ThreadPool</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Parallel+Extensions/default.aspx">Parallel Extensions</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/F_2300_/default.aspx">F#</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Talks/default.aspx">Talks</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/HPC+Server/default.aspx">HPC Server</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/C_2B002B00_/default.aspx">C++</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Visual+Studio+2010/default.aspx">Visual Studio 2010</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Agents/default.aspx">Agents</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/.NET+4/default.aspx">.NET 4</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Dryad/default.aspx">Dryad</category></item><item><title>Slides from Parallelism Tour</title><link>http://blogs.msdn.com/pfxteam/archive/2009/11/01/9916008.aspx</link><pubDate>Mon, 02 Nov 2009 02:58:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9916008</guid><dc:creator>toub</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/pfxteam/comments/9916008.aspx</comments><wfw:commentRss>http://blogs.msdn.com/pfxteam/commentrss.aspx?PostID=9916008</wfw:commentRss><wfw:comment>http://blogs.msdn.com/pfxteam/rsscomments.aspx?PostID=9916008</wfw:comment><description>&lt;P&gt;Last week, I had the privilege of touring around Tennessee, Kentucky, Ohio, and Michigan, speaking about the new parallel computing support in Visual Studio 2010 and the .NET Framework 4.&amp;nbsp; Many folks I spoke with were interested in getting a copy of the slide deck I used, so I’ve attached it to this blog post.&amp;nbsp; Enjoy!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9916008" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/pfxteam/attachment/9916008.ashx" length="2231000" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/pfxteam/archive/tags/PLINQ/default.aspx">PLINQ</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Task+Parallel+Library/default.aspx">Task Parallel Library</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/ThreadPool/default.aspx">ThreadPool</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Parallel+Extensions/default.aspx">Parallel Extensions</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Talks/default.aspx">Talks</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Coordination+Data+Structures/default.aspx">Coordination Data Structures</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Visual+Studio+2010/default.aspx">Visual Studio 2010</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/.NET+4/default.aspx">.NET 4</category></item><item><title>Task.Wait and “Inlining”</title><link>http://blogs.msdn.com/pfxteam/archive/2009/10/15/9907713.aspx</link><pubDate>Thu, 15 Oct 2009 15:45:59 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9907713</guid><dc:creator>toub</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/pfxteam/comments/9907713.aspx</comments><wfw:commentRss>http://blogs.msdn.com/pfxteam/commentrss.aspx?PostID=9907713</wfw:commentRss><wfw:comment>http://blogs.msdn.com/pfxteam/rsscomments.aspx?PostID=9907713</wfw:comment><description>&lt;p&gt;“What does Task.Wait do?” &lt;/p&gt;  &lt;p&gt;Simple question, right?&amp;#160; At a high-level, yes, the method achieves what its name implies, preventing the current thread from making forward progress past the call to Wait until the target Task has completed, one way or another.&amp;#160; If the Task ran to completion, Wait will return successfully.&amp;#160; If the Task completed due to faulting or being canceled, it will throw an exception indicating the relevant details (since the waiting code likely expects that all work to be completed by the task ran successfully if Wait returns successfully).&lt;/p&gt;  &lt;p&gt;The details are a bit more interesting.&amp;#160; Wait could simply block on some synchronization primitive until the target Task completed, and in some cases that’s exactly what it does.&amp;#160; But blocking threads is an expensive venture, in that a thread ties up a good chunk of system resources, and a blocked thread is dead weight until it’s able to continue executing useful work.&amp;#160; Instead, Wait prefers to execute useful work rather than blocking, and it has useful work at its finger tips: the Task being waited on.&amp;#160; If the Task being Wait’d on has already started execution, Wait has to block.&amp;#160; However, if it hasn’t started executing, Wait may be able to pull the target task out of the scheduler to which it was queued and execute it inline on the current thread.&lt;/p&gt;  &lt;p&gt;To do that, Wait asks for assistance from the target scheduler, by making a call to the TaskScheduler’s TryExecuteTaskInline method.&amp;#160; TryExecuteTaskInline can do whatever logic the scheduler needs in order to validate that the current context is acceptable for inlining the Task.&amp;#160; If it is, the scheduler tries to execute the task then and there as part of the call to TryExecuteTaskInline (using the base TaskScheduler’s TryExecuteTask method) and returns whether the Task could be executed.&amp;#160; If it couldn’t be executed in TryExecuteTaskInline, the scheduler returns false, and Wait will need to block until the Task completes. A Task may not be able to be executed if it’s already been or is currently being executed elsewhere. As an example of this, the default scheduler (based on the ThreadPool) is aggressive about inlining, but only if the task can be efficiently removed from the data structures that hold tasks internally in the ThreadPool (such as if the task is living in the local queue associated with the thread attempting to inline it).&lt;/p&gt;  &lt;p&gt;This is also very similar to what happens when Task.RunSynchronously is used to execute a Task (RunSynchronously may be used instead of Task.Start to run a Task currently in the TaskStatus.Created state).&amp;#160; RunSynchronously results in the Framework calling the target scheduler’s TryExecuteTaskInline, allowing the scheduler to decide whether to inline or not.&amp;#160; If the scheduler chooses not to inline, the Task will instead be queued to the scheduler, and the system will block until the Task is completed.&lt;/p&gt;  &lt;p&gt;Of course, schedulers may want to behave differently depending on whether the code is explicitly choosing to inline (e.g. RunSynchronously) or whether the inlining is happening implicitly (e.g. Wait).&amp;#160; To support this difference, in addition to accepting as a parameter the Task to be inlined, TryExecuteTaskInline also accepts as a parameter a Boolean taskWasPreviouslyQueued.&amp;#160; This value will be false if it is known that the specified task has not yet been submitted to the scheduler, and true otherwise. If RunSynchronously is being used, taskWasPreviouslyQueued will be false; if Wait, it will be true.&amp;#160; The default scheduler does, in fact, differentiate between these two cases, in that it always supports explicit inlining through RunSynchronously.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9907713" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Task+Parallel+Library/default.aspx">Task Parallel Library</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/ThreadPool/default.aspx">ThreadPool</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Parallel+Extensions/default.aspx">Parallel Extensions</category></item><item><title>TaskScheduler.FromCurrentSynchronizationContext</title><link>http://blogs.msdn.com/pfxteam/archive/2009/09/22/9898090.aspx</link><pubDate>Tue, 22 Sep 2009 19:46:13 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9898090</guid><dc:creator>toub</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/pfxteam/comments/9898090.aspx</comments><wfw:commentRss>http://blogs.msdn.com/pfxteam/commentrss.aspx?PostID=9898090</wfw:commentRss><wfw:comment>http://blogs.msdn.com/pfxteam/rsscomments.aspx?PostID=9898090</wfw:comment><description>&lt;p&gt;The Task abstractions in .NET 4 run on instances of the TaskScheduler class.&amp;#160; Two implementations of TaskScheduler ship as part of the .NET Framework 4.&amp;#160; The first is the default scheduler, which is integrated with the .NET 4 ThreadPool and takes advantage of its work-stealing queues.&amp;#160; The second is the type of TaskScheduler returned from the static method TaskScheduler.FromCurrentSynchronizationContext.&lt;/p&gt;  &lt;p&gt;According to MSDN, SynchronizationContext “provides the basic functionality for propagating a synchronization context in various synchronization models.”&amp;#160; What does that really mean?&amp;#160; At its core, SynchronizationContext provides two methods, Send and Post, both of which accept a delegate to be executed.&amp;#160; Send synchronously invokes the delegate, and Post asynchronously invokes the delegate.&amp;#160; That’s it, and the base implementation of SynchronizationContext doesn’t do anything fancier than that:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;public virtual void Send(SendOrPostCallback d, object state)     &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; d(state);      &lt;br /&gt;} &lt;/p&gt;    &lt;p&gt;public virtual void Post(SendOrPostCallback d, object state)     &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ThreadPool.QueueUserWorkItem(new WaitCallback(d.Invoke), state);      &lt;br /&gt;}&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Where things get interesting is when new types are derived from SynchronizationContext, something typically done by a UI framework (though there are other non-UI framework implementations).&amp;#160; For folks familiar with Windows Forms and Windows Presentation Framework development, you’re likely aware that UI controls should only be accessed by the thread that created them, almost always the main UI thread.&amp;#160; Thus, if a thread doing work in the background wants to update something in the UI, it needs to marshal that work back to the GUI thread so that the controls may be accessed safely.&amp;#160; Different UI frameworks expose different ways for accomplishing this marshaling.&amp;#160; For example, in Windows Forms, one uses the Invoke or BeginInvoke method of the target Control (or at least a Control created on the same thread as the target Control).&amp;#160; In WPF, one uses the target thread’s Dispatcher and corresponding Invoke/BeginInvoke&amp;#160; methods.&amp;#160; With every UI framework having its own model for marshaling work to a particular “synchronization context”, it becomes difficult to write code that supports this marshaling concept but which is agnostic to the particular environment that it’s in.&amp;#160; Enter SynchronizationContext.&amp;#160; A new type may be derived from SynchronizationContext such that its Send method synchronously marshals a delegate to the right thread for execution, and Post does the same but asynchronously.&amp;#160; If you look at the implementations of the SynchronizationContexts provided by Windows Forms and WPF, that’s exactly what they do, delegating to the relevant Invoke/BeginInvoke methods from Send and Post to marshal the work correctly.&lt;/p&gt;  &lt;p&gt;To make it easy to get at the right SynchronizationContext, a UI framework like Windows Forms will publish an instance of its SynchronizationContext-derived class to SynchronizationContext.Current.&amp;#160; Code can then grab SynchronizationContext.Current and use it to marshal work, without having to know whether it’s being used from Windows Forms or Windows Presentation Foundation or another similar model.&lt;/p&gt;  &lt;p&gt;“TaskScheduler.FromCurrentSynchronizationContext” should now make more sense.&amp;#160; This method creates a TaskScheduler that wraps the SynchronizationContext returned from SynchronizationContext.Current.&amp;#160; Thus, this gives you a TaskScheduler that will execute Tasks on the current SynchronizationContext.&amp;#160; Why is that useful?&amp;#160; It means you can create Tasks that are able to access UI controls safely, simply by running them on the right scheduler.&amp;#160; &lt;/p&gt;  &lt;p&gt;Let’s say that I wanted to load three images from some data source.&amp;#160; When those images have been loaded, I want to blend them all together, and then I want to display the result into a PictureBox on my UI.&amp;#160; Using Tasks and TaskScheduler.FromCurrentSynchronizationContext, I could write code like the following:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;private void Button1_Click(…)     &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; var ui = TaskScheduler.FromCurrentSynchronizationContext();      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; var tf = Task.Factory;      &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; // Load the three images asynchronously      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; var imageOne = tf.StartNew(() =&amp;gt; LoadFirstImage());      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; var imageTwo = tf.StartNew(() =&amp;gt; LoadSecondImage());      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; var imageThree = tf.StartNew(() =&amp;gt; LoadThirdImage());      &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; // When they’ve been loaded, blend them      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; var blendedImage = tf.ContinueWhenAll(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; new [] { imageOne, imageTwo, imageThree }, _ =&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; BlendImages(imageOne.Result, imageTwo.Result, imageThree.Result));      &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; // When we’re done blending, display the blended image      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; blendedImage.ContinueWith(_ =&amp;gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; pictureBox1.Image = blendedImage.Result;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }, ui);      &lt;br /&gt;}&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This code runs three tasks to load the three input images asynchronously.&amp;#160; When all of those have been loaded, again asynchronously some BlendImages method is used to blend the images, taking the three inputs and returning the blended image.&amp;#160; Finally, once that’s done, another task is used to render the blended image by storing it into a PictureBox on the UI.&amp;#160; Since this modifies a UI control, we need to do it from the UI thread.&amp;#160; Thus, we pass a TaskScheduler to the ContinueWith method; this scheduler targets the UI’s SynchronizationContext, and will cause the Task to execute on the UI thread.&lt;/p&gt;  &lt;p&gt;TaskScheduler.FromCurrentSynchronizationContext is provided for convenience and because this is a very common need.&amp;#160; However, due to TaskScheduler’s extensibility, it’s actually possible to implement this behavior yourself, and in doing so you could modify it to suit your own needs however you see fit.&lt;/p&gt;  &lt;p&gt;Let’s say you did want to develop a new SynchronizationContextTaskScheduler.&amp;#160; It might look something like this:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;public class SynchronizationContextTaskScheduler : TaskScheduler     &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; private ConcurrentQueue&amp;lt;Task&amp;gt; _tasks = new ConcurrentQueue&amp;lt;Task&amp;gt;();      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; private SynchronizationContext _context;&lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; public SynchronizationContextTaskScheduler() :      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this(SynchronizationContext.Current) { } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; public SynchronizationContextTaskScheduler(     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; SynchronizationContext context)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (context == null) throw new ArgumentNullException(&amp;quot;context&amp;quot;);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; _context = context;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; protected override void QueueTask(Task task)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // Add the task to the collection      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; _tasks.Enqueue(task);      &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // Queue up a delegate that will dequeue and execute a task      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; _context.Post(delegate      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Task toExecute;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (_tasks.TryDequeue(out toExecute)) TryExecuteTask(toExecute);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }, null);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; protected override bool TryExecuteTaskInline(     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Task task, bool taskWasPreviouslyQueued)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return SynchronizationContext.Current == _context &amp;amp;&amp;amp;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; TryExecuteTask(task);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; public override int MaximumConcurrencyLevel { get { return 1; } } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; protected override IEnumerable&amp;lt;Task&amp;gt; GetScheduledTasks()     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return _tasks.ToArray();      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;}&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Not a lot of code for a fairly powerful thing.&amp;#160; &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;The constructors simply accept the target SynchronizationContext and store it, also initializing a thread-safe queue that will store the tasks to be executed.&amp;#160; &lt;/li&gt;    &lt;li&gt;The QueueTask method is called whenever the system is providing a Task for this scheduler to execute: this scheduler handles it by storing that Task into a queue, and then Post’ing to the SynchronizationContext a delegate that will pull the next Task from the queue and execute it.&amp;#160; &lt;/li&gt;    &lt;li&gt;The TryExecuteTaskInline is invoked any time the system wants to run a Task inline on the current thread (either from a call to RunSynchronously or from a Wait attempt): we need to make sure that the call is coming from the same SynchronizationContext as the target, otherwise we may end up running in the wrong context.&lt;/li&gt;    &lt;li&gt;We only intended to support SynchronizationContexts that represent a single thread of execution (that’s most common), so we return 1 from MaximumConcurrencyLevel.&lt;/li&gt;    &lt;li&gt;And we want the debugger to be able to display tasks scheduled to this scheduler, so we override GetScheduledTasks to return an array of the tasks queued. (This is why we need to explicitly store the queue of tasks; otherwise, we could have simply relied on lambda closures to capture each task to be executed.)&lt;/li&gt; &lt;/ul&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9898090" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Task+Parallel+Library/default.aspx">Task Parallel Library</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/ThreadPool/default.aspx">ThreadPool</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Code+Samples/default.aspx">Code Samples</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Parallel+Extensions/default.aspx">Parallel Extensions</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Visual+Studio+2010/default.aspx">Visual Studio 2010</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/.NET+4.0/default.aspx">.NET 4.0</category></item><item><title>TaskCreationOptions.PreferFairness</title><link>http://blogs.msdn.com/pfxteam/archive/2009/07/07/9822857.aspx</link><pubDate>Tue, 07 Jul 2009 19:08:38 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9822857</guid><dc:creator>toub</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/pfxteam/comments/9822857.aspx</comments><wfw:commentRss>http://blogs.msdn.com/pfxteam/commentrss.aspx?PostID=9822857</wfw:commentRss><wfw:comment>http://blogs.msdn.com/pfxteam/rsscomments.aspx?PostID=9822857</wfw:comment><description>&lt;p&gt;One of the ways in which the Task Parallel Library achieves good performance is through “work-stealing”.&amp;#160; Work-stealing is supported in the &lt;a href="http://blogs.msdn.com/ericeil/archive/2009/04/23/clr-4-0-threadpool-improvements-part-1.aspx"&gt;.NET 4 ThreadPool&lt;/a&gt; for access through the Task Parallel Library and its default scheduler.&amp;#160; This manifests as every thread in the ThreadPool having its own queue for work; when that thread creates Tasks, by default these tasks are enqueued into the thread’s local queue, rather than into the global queue that a call to ThreadPool.QueueUserWorkItem would typically target.&amp;#160; When a thread goes in search for work to be executed, it starts with its local queue, an operation which enable some extra efficiencies due to improved cache locality, minimized contention, and so forth.&amp;#160; However, this logic also affects fairness.&lt;/p&gt;  &lt;p&gt;A typical thread pool will have a single queue that maintains all of the work to be executed.&amp;#160; When threads in the pool are ready to process another work item, they’ll dequeue the work from the head of the queue, and when new work arrives to be executed by the pool, it’ll be enqueued onto the queue’s tail.&amp;#160; This provides a level of fairness between work items, in that work items that arrive first are more likely to be picked off and start executing first.&lt;/p&gt;  &lt;p&gt;Work-stealing perturbs that fairness.&amp;#160; Threads external to the pool could be queuing up work, but if the threads in the pool are also generating work, the work generated by the pool will be preferred over the other work items, based on the search order employed by the threads in the pool (which start searching for work first with their local queues, only proceeding on to the global queue and then on to other threads’ queues if work wasn’t available locally).&amp;#160; This behavior is typically expected and even desired, in that if a work item being executed is generating more work, that generated work is typically considered part of the overall operation being processed, and thus it makes sense it would be preferred over other unrelated work.&amp;#160; For example, imagine a quicksort operation, where each recursive sort invocation potentially results in several further recursive calls; those calls, which in a parallel implementation are likely individual tasks, are part of the all-up sort operation.&lt;/p&gt;  &lt;p&gt;Still, there are some scenarios where this default behavior is inappropriate, where fairness should be maintained between particular work items generated by threads in the pool and work items generated by other threads.&amp;#160; This is often the case for long chains of continuations, where the work generated isn’t considered part of the current work but rather a follow-on to the current work.&amp;#160; In those cases, you may want that follow-on work to be prioritized in a fair manner with other work in the system.&amp;#160; This is where TaskCreationOptions.PreferFairness can prove useful.&lt;/p&gt;  &lt;p&gt;When a Task is scheduled to the default scheduler, the scheduler looks to see whether the current thread from which the Task is being queued is a ThreadPool thread that has its own local queue.&amp;#160; If it isn’t, the work item will be queued to the global queue.&amp;#160; If it is, the scheduler will also check whether the TaskCreationOptions value for the Task includes the PreferFairness flag, which is not on by default.&amp;#160; If the flag is set, even if the thread does have its own local queue, the scheduler will still enqueue the Task to the global queue rather than to the local queue.&amp;#160; In this manner, that Task will be considered fairly along with all other work items queued globally.&lt;/p&gt;  &lt;p&gt;What was just described is the current implementation of the PreferFairness flag in the default scheduler.&amp;#160; The implementation could of course change, but what won’t change is the purpose of the flag: by specifying PreferFairness, you’re telling the system that this Task shouldn’t be prioritized just because it’s coming from a local queue.&amp;#160; You’re telling the system that you want the system to do its best to ensure that this Task is prioritized in a first-come, first-serve nature.&lt;/p&gt;  &lt;p&gt;One other thing to note is that Task itself knows nothing of this flag; it’s just a flag set as an option on the Task.&amp;#160; It’s the scheduler that decides how it wants to handle this particular option, just as with TaskCreationOptions.LongRunning.&amp;#160; The default scheduler handles it as described above, but another scheduler (such as one you write) may do with this flag whatever it wants, including ignoring it.&amp;#160; Hence the naming “Prefer” rather than something stricter like “Guarantee”.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9822857" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Task+Parallel+Library/default.aspx">Task Parallel Library</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/ThreadPool/default.aspx">ThreadPool</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Parallel+Extensions/default.aspx">Parallel Extensions</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/.NET+4.0/default.aspx">.NET 4.0</category></item><item><title>Tasks and Unhandled Exceptions</title><link>http://blogs.msdn.com/pfxteam/archive/2009/05/31/9674669.aspx</link><pubDate>Mon, 01 Jun 2009 07:34:11 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9674669</guid><dc:creator>toub</dc:creator><slash:comments>8</slash:comments><comments>http://blogs.msdn.com/pfxteam/comments/9674669.aspx</comments><wfw:commentRss>http://blogs.msdn.com/pfxteam/commentrss.aspx?PostID=9674669</wfw:commentRss><wfw:comment>http://blogs.msdn.com/pfxteam/rsscomments.aspx?PostID=9674669</wfw:comment><description>&lt;p&gt;Prior to the .NET Framework 2.0, unhandled exceptions were largely ignored by the runtime.&amp;#160; For example, if a work item queued to the ThreadPool threw an exception that went unhandled by that work item, the ThreadPool would eat that exception and continue on its merry way.&amp;#160; Similarly, if a finalizer running on the finalizer thread threw an exception, the system would eat the exception and continue on executing other finalizers.&lt;/p&gt;  &lt;p&gt;That changed for .NET 2.0.&amp;#160; Exceptions are meant to indicate a problem, and automatically eating unhandled exceptions often hides significant errors and reliability problems in an application.&amp;#160; As such, for .NET 2.0, this unhandled exception behavior was changed by default to more closely match how exceptions are handled by Windows in general: if an exception goes unhandled, the process comes crashing down.&amp;#160; While this may seem harsh, allowing the process to crash typically makes it easier to catch an underlying problem, but more importantly, it prevents the application from continuing to hobble along in a potentially very bad state, with corrupted data, etc.&amp;#160; Thus, since .NET 2.0, if a work item running on the ThreadPool throws an unhandled exception, by default the process crashes.&lt;/p&gt;  &lt;p&gt;There’s a notable exemption to this behavior, even after 2.0: the Asynchronous Programming Model (APM) pattern.&amp;#160; With the APM pattern, work is started asynchronously with a BeginXx method, and at some point later the results of the work are retrieved with a corresponding EndXx method.&amp;#160; If the asynchronous work throws an exception, that exception is then propagated out of the call to the EndXx method when the EndXx method is invoked.&amp;#160; This, of course, counts on the EndXx method being invoked.&amp;#160; If the developer makes a mistake such that End is never invoked, any exception that occurred as part of the asynchronous invocation will likely go unnoticed, as would have happened in more situations in .NET 1.x.&lt;/p&gt;  &lt;p&gt;With Tasks in .NET 4.0, we face a similar situation as does the APM pattern.&amp;#160; A Task represents an asynchronous operation that may throw an unhandled exception, but unlike work items generated by ThreadPool.QueueUserWorkItem, a Task instance is used to later join with the asynchronous work.&amp;#160; As such, any unhandled exceptions will be stored into the relevant Task instance, later thrown any time that Task is waited on (and also available through the Task’s Exception property).&amp;#160; In fire-and-forget scenarios, where the developer has no intention of joining with the Task, or if the developer simply forgets to join with the Task, the exception may never be observed, and thus if we did nothing special, we’d be in a bad situation very much like that which the APM pattern faces with unhandled exceptions.&lt;/p&gt;  &lt;p&gt;To address this, Tasks keep track of whether an unhandled exception has been “observed.”&amp;#160; In this context, “observed” means that code has joined with the Task in some fashion in order to at least be made aware of the exception.&amp;#160; This could be calling Wait/WaitAll on the Task.&amp;#160; It could be checking the Task’s Exception property after the Task has completed.&amp;#160; Or it could be using a Task&amp;lt;TResult&amp;gt;’s Result property.&amp;#160; If a Task sees that its exception has been observed in some manner, life is good.&amp;#160; If, however, all references to a Task are removed (making the Task available for garbage collection), and if its exception hasn’t yet been observed, the Task knows that its exception will never be observed.&amp;#160; In such a case, the Task takes advantage of finalization, and uses a helper object to propagate the unhandled exception on the finalizer thread.&amp;#160; With the behavior described earlier, that exception on the finalizer thread will go unhandled and invoke the default unhandled exception logic, which is to log the issue and crash the process.&lt;/p&gt;  &lt;p&gt;In this manner, we can have our cake and eat it, too.&amp;#160; As with the APM, we make any exceptions that occurred asynchronously available later for the app to retrieve.&amp;#160; And as with work items on the ThreadPool, if an exception goes unhandled, it will cause the process to be torn down.&lt;/p&gt;  &lt;p&gt;Of course, there may still be situations where you do want a fire-and-forget task, but where you want to automatically “observe” any unhandled exception, either to log it or something similar, or just to prevent the process from crashing in a situation where you know the exception will be benign.&amp;#160; In that case, you can take advantage of continuations to address your needs.&lt;/p&gt;  &lt;p&gt;Consider a Task &lt;em&gt;t&lt;/em&gt;.&amp;#160; After creating the Task, I can run code like the following:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;t.ContinueWith(c =&amp;gt; { var ignored = c.Exception; },      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; TaskContinuationOptions.OnlyOnFaulted |       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; TaskContinuationOptions.ExecuteSynchronously |      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; TaskContinuationOptions.DetachedFromParent);&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This code creates a continuation off of Task &lt;em&gt;t&lt;/em&gt; that will only be scheduled if Task &lt;em&gt;t&lt;/em&gt; completes in a Faulted state, meaning that it completed due to an exception going unhandled.&amp;#160; When this continuation runs, it will observe the Task’s exception, preventing it from getting finalized.&amp;#160; You could even wrap this kind of logic up into an extension method, such as:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;public static Task IgnoreExceptions(this Task task)      &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; task.ContinueWith(c =&amp;gt; { var ignored = c.Exception; },       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; TaskContinuationOptions.OnlyOnFaulted |       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; TaskContinuationOptions.ExecuteSynchronously |      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; TaskContinuationOptions.DetachedFromParent);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return task;       &lt;br /&gt;}&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;With this in hand, any time I create a fire-and-forget Task where I want an unhandled exception to be ignored, I can simply tag on IgnoreExceptions, e.g. instead of:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;var t = Task.Factory.StartNew(…);&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;I could write:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;var t = Task.Factory.StartNew(…).IgnoreExceptions();&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Of course, the exception handling logic in Task exists for good reasons, to prevent unhandled exceptions from going unnoticed, and as such it’s not a great idea to liberally sprinkle use of an IgnoreExceptions extension method like this.&amp;#160; But in some situations, it can be quite useful.&lt;/p&gt;  &lt;p&gt;There’s a corollary to IgnoreExceptions which may also be useful.&amp;#160; One of the downsides to the logic we use to tear down the process is that it relies on finalization.&amp;#160; Finalization isn’t guaranteed to occur in a timely fashion, so an exception may go unhandled and it may be some time before the app then crashes; some time is better than never, but it’s still not ideal.&amp;#160; If you want a more timely crash, you could use an extension method like the following:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;public static Task FailFastOnException(this Task task)      &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; task.ContinueWith(c =&amp;gt; Environment.FailFast(“Task faulted”, c.Exception),       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; TaskContinuationOptions.OnlyOnFaulted |       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; TaskContinuationOptions.ExecuteSynchronously |      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; TaskContinuationOptions.DetachedFromParent);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return task;       &lt;br /&gt;}&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Rather than ignoring the exception, this uses Environment.FailFast to immediately crash the process.&amp;#160; In this manner, I could write code like the following:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;var t = Task.Factory.StartNew(…).FailFastOnException();&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;and as soon as Task t faults, the process will crash.&amp;#160; This could be beneficial when debugging, as you’ll know immediately when something goes wrong.&amp;#160; There are lots of variations on this as well.&amp;#160; Debugger.Break could be used to immediately break into an attached debugger, you could raise an event of your choosing, the exception could be logged to an application log file, and so forth.&amp;#160; In this manner, continuations are quite powerful.&lt;/p&gt;  &lt;p&gt;(For anyone interested in extending Parallel Extensions with extension methods like this, the Parallel Extensions Extras project in the Beta 1 samples available at &lt;a title="http://code.msdn.microsoft.com/ParExtSamples" href="http://code.msdn.microsoft.com/ParExtSamples"&gt;http://code.msdn.microsoft.com/ParExtSamples&lt;/a&gt;&lt;strong&gt;&amp;#160;&lt;/strong&gt;includes a plethora of interesting and useful examples. Enjoy!)&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9674669" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Task+Parallel+Library/default.aspx">Task Parallel Library</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/ThreadPool/default.aspx">ThreadPool</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Code+Samples/default.aspx">Code Samples</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Parallel+Extensions/default.aspx">Parallel Extensions</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/.NET+4.0/default.aspx">.NET 4.0</category></item><item><title>Concurrent, Multi-core Programming on Windows and .NET</title><link>http://blogs.msdn.com/pfxteam/archive/2008/10/27/9019731.aspx</link><pubDate>Tue, 28 Oct 2008 08:51:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9019731</guid><dc:creator>toub</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/pfxteam/comments/9019731.aspx</comments><wfw:commentRss>http://blogs.msdn.com/pfxteam/commentrss.aspx?PostID=9019731</wfw:commentRss><wfw:comment>http://blogs.msdn.com/pfxteam/rsscomments.aspx?PostID=9019731</wfw:comment><description>&lt;P&gt;Thanks to everyone who attended our PDC pre-conference session yesterday on parallelism and concurrency!&amp;nbsp; We had a wonderful turnout at the event, and David, Joe, and I all had a terrific time. &lt;A class="" href="http://blogs.msdn.com/pfxteam/attachment/9019731.ashx" mce_href="http://blogs.msdn.com/pfxteam/attachment/9019731.ashx"&gt;Attached&lt;/A&gt; to this post are the slides we presented.&lt;/P&gt;
&lt;P&gt;(It turns out that the PDC site does allow you to &lt;A href="https://sessions.microsoftpdc.com/public/evals.aspx" mce_href="https://sessions.microsoftpdc.com/public/evals.aspx"&gt;submit an evaluation&lt;/A&gt; for a precon.&amp;nbsp; If you attended, we'd love your &lt;A href="https://sessions.microsoftpdc.com/public/evals.aspx" mce_href="https://sessions.microsoftpdc.com/public/evals.aspx"&gt;feedback&lt;/A&gt;.)&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9019731" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/pfxteam/attachment/9019731.ashx" length="1451170" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/pfxteam/archive/tags/PLINQ/default.aspx">PLINQ</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Task+Parallel+Library/default.aspx">Task Parallel Library</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/ThreadPool/default.aspx">ThreadPool</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Parallelism+Blockers/default.aspx">Parallelism Blockers</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Code+Samples/default.aspx">Code Samples</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Parallel+Extensions/default.aspx">Parallel Extensions</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Talks/default.aspx">Talks</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/C_2B002B00_/default.aspx">C++</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Tools/default.aspx">Tools</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Coordination+Data+Structures/default.aspx">Coordination Data Structures</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Release/default.aspx">Release</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/CTP/default.aspx">CTP</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/CDS/default.aspx">CDS</category></item><item><title>Q&amp;As from the 2008 Financial Services Developer Conference</title><link>http://blogs.msdn.com/pfxteam/archive/2008/04/03/8354128.aspx</link><pubDate>Thu, 03 Apr 2008 18:27:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8354128</guid><dc:creator>toub</dc:creator><slash:comments>9</slash:comments><comments>http://blogs.msdn.com/pfxteam/comments/8354128.aspx</comments><wfw:commentRss>http://blogs.msdn.com/pfxteam/commentrss.aspx?PostID=8354128</wfw:commentRss><wfw:comment>http://blogs.msdn.com/pfxteam/rsscomments.aspx?PostID=8354128</wfw:comment><description>&lt;P&gt;A few weeks ago, I presented on &lt;A href="http://www.microsoft.com/downloads/details.aspx?FamilyID=e848dc1d-5be3-4941-8705-024bc7f180ba&amp;amp;displaylang=en" mce_href="http://www.microsoft.com/downloads/details.aspx?FamilyID=e848dc1d-5be3-4941-8705-024bc7f180ba&amp;amp;displaylang=en"&gt;Parallel Extensions to the .NET Framework&lt;/A&gt; at the 6th annual Microsoft &lt;A href="http://www.financialdevelopers.com/" mce_href="http://www.financialdevelopers.com/"&gt;Financial Services&lt;/A&gt; Developer Conference (the decks from the conference are &lt;A href="http://www.financialdevelopers.com/conferencedecks.aspx" mce_href="http://www.financialdevelopers.com/conferencedecks.aspx"&gt;now available online&lt;/A&gt;).&amp;nbsp; I had a great time and a great audience, and during the presentation on Thursday I received some good questions.&amp;nbsp; Here are some of them along with answers.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;BR&gt;Question:&lt;/STRONG&gt; This stuff looks really cool, but why do we need to modify our code to use Parallel Extensions; why can't you just automatically parallelize it for me?&lt;/P&gt;
&lt;P&gt;Igor Ostrovsky, a developer on our team, has a nice set of explanations in his responses to some questions on the &lt;A href="http://forums.microsoft.com/MSDN/ShowForum.aspx?ForumID=1986&amp;amp;SiteID=1" mce_href="http://forums.microsoft.com/MSDN/ShowForum.aspx?ForumID=1986&amp;amp;SiteID=1"&gt;Parallel Extensions MSDN Forums&lt;/A&gt;:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;"The way we traditionally express programs makes it very difficult for the compiler to understand the code at a high level, and parallelize the work. (A part of the problem is that understanding code at a high level is in some sense impossible - see the &lt;A href="http://en.wikipedia.org/wiki/Halting_problem" mce_href="http://en.wikipedia.org/wiki/Halting_problem"&gt;halting problem&lt;/A&gt;.) However, the user can help the parallel engine in various ways: &lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;The user expresses the goal of the computation instead of the explicit steps to perform it (e.g. Parallel LINQ). &lt;/LI&gt;
&lt;LI&gt;The user tells the parallel engine how to parallelize the computation (e.g. Task Parallel Library) &lt;/LI&gt;
&lt;LI&gt;The user specifies certain invariants of the code (e.g. which parts are atomic - transactional memory)" &lt;/LI&gt;&lt;/UL&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;BR&gt;Question:&lt;/STRONG&gt; Parallel Extensions looks like a great way to express concurrency in my applications, but how will I then debug my apps?&amp;nbsp; Debugging parallel applications today is really hard... what are you doing about that?&lt;/P&gt;
&lt;P&gt;It most certainly is hard, and we fully realize that developing software doesn’t begin and end with writing code.&amp;nbsp; Tools are incredibly important in the life cycle of applications, especially when it comes to debugging and improving performance.&amp;nbsp; This is never more true than when writing parallel applications, as concurrency introduces a whole host of issues that can be very difficult to find and fix.&amp;nbsp; Alongside Parallel Extensions, the Parallel Computing Platform team is investing in the development of debugging and profiling tools that will increase developer productivity and improve the correctness and maintainability of parallel code.&amp;nbsp; We haven't released previews of these tools yet, but you can expect to see them in the future.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;BR&gt;Question:&lt;/STRONG&gt; Do you need multiple cores or multiple processors to do multithreading? Is it possible to use Parallel Extensions on a single CPU machine, and if so, is there overhead in doing so?&lt;/P&gt;
&lt;P&gt;Even with a single CPU, there are many places where multithreading can provide significant value.&amp;nbsp; For example, in GUI programming on Windows, doing any significant work on the main GUI thread will cause user interaction with the application to suffer.&amp;nbsp; Instead, it's better to offload work to a background thread, which can do processing while allowing the application to stay responsive.&amp;nbsp; But when it comes to computationally-intensive tasks, multithreading on a single CPU can lead to decreased performance.&amp;nbsp; Parallel Extensions seeks to minimize that decrease in performance.&amp;nbsp; It can be used on a machine with a single CPU; the idea is that you write your code using Parallel Extensions correctly, and it will then help your application to scale from one to many cores.&amp;nbsp; There is overhead to using Parallel Extensions (as there will be for pretty much any parallel framework), but we're working hard to minimize that overhead, and for many problems on multi-core machines, the overhead introduced will be greatly dwarfed by the parallel benefits received.&amp;nbsp; On a single CPU, we can typically reduce the overhead to the point where for any problem that would have benefited from parallelism on a multi-core machine, the overhead will be negligible on a single core.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;BR&gt;Question:&lt;/STRONG&gt; Can one mix and match Parallel Extensions with existing concurrency mechanisms?&amp;nbsp; For example, can I use the .NET ThreadPool in the same application as Parallel Extensions?&amp;nbsp; Can I use monitors and mutexes and sempahores and reader-writer locks with Parallel Extensions just as I do with threads today?&lt;/P&gt;
&lt;P&gt;Yes, to all of your questions.&amp;nbsp; Parallel Extensions relies on threads, so you can continue to use existing synchronization primitives with Parallel Extensions just as you would with threads you spin up manually or with threads from the ThreadPool; we're also introducing some new synchronization and coordination primitives in upcoming releases of Parallel Extensions, so stay tuned for those.&amp;nbsp; (Note, however, that there are some corner-case rules to be aware of. As an example, don’t evaluate futures or wait on tasks while holding a reentrant lock. Doing so isn't implicitly a problem, but it could lead to some issues that you'll need to be aware of; I'll dive into this further in a future blog post.)&lt;/P&gt;
&lt;P&gt;&lt;BR&gt;&lt;STRONG&gt;Question:&lt;/STRONG&gt; What is the relationship between HPC Server and Parallel Extensions?&amp;nbsp; Does one replace the other?&lt;/P&gt;
&lt;P&gt;Neither replaces the other, and in fact they're useful in combination.&amp;nbsp; &lt;A href="http://www.microsoft.com/hpc" mce_href="http://www.microsoft.com/hpc"&gt;HPC Server&lt;/A&gt; is all about scaling out to nodes in a cluster of machines, and Parallel Extensions is all about scaling up on an individual machine.&amp;nbsp; Just as you can use Parallel Extensions to parallelize your desktop applications, you can use Parallel Extensions to parallelize the .NET applications running on nodes in your cluster.&amp;nbsp; This can be quite powerful when used in conjunction with HPC Server functionality like the new WCF-based &lt;A href="http://blogs.msdn.com/philpenn/archive/2007/11/21/new-hpc-wcf-feature-use-compute-cluster-as-scalable-soa-platform.aspx" mce_href="http://blogs.msdn.com/philpenn/archive/2007/11/21/new-hpc-wcf-feature-use-compute-cluster-as-scalable-soa-platform.aspx"&gt;SOA Service Broker&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;&lt;BR&gt;&lt;STRONG&gt;Question:&lt;/STRONG&gt; Is there any way to hook into the scheduler used by Parallel Extensions to automatically fan out the work to a cluster?&lt;/P&gt;
&lt;P&gt;The scheduler in Parallel Extensions is not currently extensible in this way.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Question:&lt;/STRONG&gt; Will the thread pool used by Parallel Extensions allow additional threads to be introduced when the number of cores increases?&lt;/P&gt;
&lt;P&gt;Absolutely.&amp;nbsp; When the threads in the pool are all being used to do useful work, the scheduler tries to maintain a ratio of one thread per core, so more cores typically translates to more threads.&amp;nbsp; But in a variety of situations that ratio will not always be 1:1.&amp;nbsp; In some cases, more threads may be used, such as if threads block (e.g. synchronization, I/O, etc.) or the user explicitly requests more threads through a TaskManagerPolicy.&amp;nbsp; Similarly, a TaskManagerPolicy can be used to dial down the amount of available concurrency.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Question: Could you run out of memory if you have a large number of tasks?&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Tasks are objects just like any other in .NET, and are subject to the same memory constraints as any other managed code.&amp;nbsp; In the same vein, they're also managed by the CLR's garbage collector, such that completed tasks with no references left to them may be collected. &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Question: Why will this be faster than using the ThreadPool?&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;There are a variety of reasons a work-stealing scheduler can perform better than a typical thread pool.&amp;nbsp; For one, the scheduler in Parallel Extensions enables more scalable queue management in that it's not bottlenecked on a single queue storing all work items.&amp;nbsp; Work items are distributed amongst multiple queues, ideally limiting contention on a single queue for all work; this becomes more and more important as the size of the work items decreases, as the number of threads contending for work increases, and as the number of cores running that work increases.&amp;nbsp; These processor-local queues also enable lock-freedom, which contributes to the efficiency of retrieving work items and executing them.&amp;nbsp; There are other significant benefits related to work-stealing for many types of problems, such as very efficient queueing mechanisms when creating tasks recursively.&amp;nbsp; Moreover, the design can provide significant improvements to things like memory locality, which can greatly improve an algorithm's performance.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Question: If I'm testing my code on a single-core machine, can I simulate more cores?&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;To some extent.&amp;nbsp; With the PLINQ programming model exposed in the CTP, you can provide a degree of parallelism value to the AsParallel extension method, which controls the number of threads that can be used to execute the query; by default on a single-core machine, this value will be 1, but you can explicitly make it larger.&amp;nbsp; And for the Task Parallel Library, you can create new TaskManagers with specific TaskManagerPolicy instances that increase the number of threads that can be used beyond the number of cores on the machine. However, while it is possible to simulate it this way, your application won't be subject to some of the complexities of having multiple cores, and as a result some bugs in the parallel implementation may remain hidden or get hit with much less frequently.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Question: Does Parallel Extensions use threads or fibers?&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Threads.&amp;nbsp; Avoid using fibers in managed code: see &lt;A title=http://www.bluebytesoftware.com/blog/PermaLink,guid,2d0038b5-7ba5-421f-860b-d9282a1211d3.aspx href="http://www.bluebytesoftware.com/blog/PermaLink,guid,2d0038b5-7ba5-421f-860b-d9282a1211d3.aspx" mce_href="http://www.bluebytesoftware.com/blog/PermaLink,guid,2d0038b5-7ba5-421f-860b-d9282a1211d3.aspx"&gt;http://www.bluebytesoftware.com/blog/PermaLink,guid,2d0038b5-7ba5-421f-860b-d9282a1211d3.aspx&lt;/A&gt; for more details.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Question: If I spin up a task, and it throws an exception, where will that exception bubble up?&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Just as with the Asynchronous Programming Model pattern, where exceptions thrown during asynchronous execution are reraised when the EndXx method is called, exceptions thrown during the execution of a task will be reraised when the Task is waited on (e.g. task.Wait()).&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8354128" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Task+Parallel+Library/default.aspx">Task Parallel Library</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/ThreadPool/default.aspx">ThreadPool</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Parallel+Extensions/default.aspx">Parallel Extensions</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Talks/default.aspx">Talks</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/HPC+Server/default.aspx">HPC Server</category></item><item><title>Wrapping an APM implementation with Future&lt;T&gt;</title><link>http://blogs.msdn.com/pfxteam/archive/2008/03/16/8272833.aspx</link><pubDate>Sun, 16 Mar 2008 22:59:32 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8272833</guid><dc:creator>toub</dc:creator><slash:comments>8</slash:comments><comments>http://blogs.msdn.com/pfxteam/comments/8272833.aspx</comments><wfw:commentRss>http://blogs.msdn.com/pfxteam/commentrss.aspx?PostID=8272833</wfw:commentRss><wfw:comment>http://blogs.msdn.com/pfxteam/rsscomments.aspx?PostID=8272833</wfw:comment><description>&lt;p&gt;In a previous post, I talked about &lt;a href="http://blogs.msdn.com/pfxteam/archive/2008/02/29/7960146.aspx"&gt;implementing the Asynchronous Programming Model&lt;/a&gt; pattern using Future&amp;lt;T&amp;gt; from &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=e848dc1d-5be3-4941-8705-024bc7f180ba"&gt;Parallel Extensions to the .NET Framework&lt;/a&gt;.&amp;nbsp; It's also possible to go in the opposite direction, to create a Future&amp;lt;T&amp;gt; from an existing APM implementation.&lt;/p&gt; &lt;p&gt;As has been shown in previous examples, in this example we'll take advantage of the "promise" capabilities provided by Future&amp;lt;T&amp;gt;.&amp;nbsp; This allows a Future&amp;lt;T&amp;gt; to be created without a Func&amp;lt;T&amp;gt; delegate, such that the future's Value and Exception properties can be set explicitly, but only once; any thread waiting on the Future&amp;lt;T&amp;gt; will block until one of these properties is set.&lt;/p&gt; &lt;blockquote&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Future&lt;/span&gt;&amp;lt;T&amp;gt; Create&amp;lt;T&amp;gt;(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;Action&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;AsyncCallback&lt;/span&gt;&amp;gt; beginFunc, &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;Func&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;IAsyncResult&lt;/span&gt;, T&amp;gt; endFunc)&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;var &lt;/span&gt;f = &lt;span style="color: #2b91af"&gt;Future&lt;/span&gt;&amp;lt;T&amp;gt;.Create();&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;beginFunc(iar =&amp;gt; {&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;try&lt;/span&gt; { f.Value = endFunc(iar); }&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;catch&lt;/span&gt; (&lt;span style="color: #2b91af"&gt;Exception&lt;/span&gt; e) { f.Exception = e; }&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;});&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;return&lt;/span&gt; f;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;}&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;This Create&amp;lt;T&amp;gt; method first creates a Future&amp;lt;T&amp;gt; as a promise.&amp;nbsp; It then calls a delegate provided by the caller to start the asynchronous action using the relevant BeginXx method; as an argument to that action, this code passes a delegate that will be called back by the asynchronous operation when it completes; the APM method will pass an IAsyncResult, which will then be passed in this callback to the endFunc delegate provided by the caller.&amp;nbsp; That endFunc will call the EndXx method, and will use the resulting value or exception to set the Future&amp;lt;T&amp;gt;.&lt;/p&gt; &lt;p&gt;As an example of using this, consider a FileStream.&amp;nbsp; FileStream exposes a BeginRead method:&lt;/p&gt; &lt;blockquote&gt; &lt;p class="MsoNormal"&gt;&lt;span style="font-size: 10pt; color: #2b91af; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;IAsyncResult&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; BeginRead(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue"&gt;byte&lt;/span&gt;[] array, &lt;span style="color: blue"&gt;int&lt;/span&gt; offset, &lt;span style="color: blue"&gt;int&lt;/span&gt; numBytes, &lt;span style="color: #2b91af"&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; AsyncCallback&lt;/span&gt; userCallback, &lt;span style="color: blue"&gt;object&lt;/span&gt; stateObject)&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;as well as a corresponding EndRead method:&lt;/p&gt; &lt;blockquote&gt; &lt;p class="MsoNormal"&gt;&lt;span style="font-size: 10pt; color: blue; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;int&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; EndRead(&lt;span style="color: #2b91af"&gt;IAsyncResult&lt;/span&gt; asyncResult);&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;If we want to create a Future&amp;lt;T&amp;gt; that represents an asynchronous read operation on a FileStream, we could do so with our new Create method as follows:&lt;/p&gt; &lt;blockquote&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; color: blue; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;var&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; readFuture = Create&amp;lt;&lt;span style="color: blue"&gt;int&lt;/span&gt;&amp;gt;(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;ac =&amp;gt; fs.BeginRead(buffer, 0, buffer.Length, ac, &lt;span style="color: blue"&gt;null&lt;/span&gt;),&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;fs.EndRead);&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;I can now go off and do something else, and when I later get readFuture's Value, I'll block until the asynchronous operation completes (or return immediately with the result if it's already completed).&amp;nbsp; If the FileStream was created to support asynchronous I/O operations and if the underlying version of Windows supports asynchronous I/O, while the read request is happening, no threads will be used, and yet I'll still have a valid Future&amp;lt;T&amp;gt; to represent the operation.&lt;/p&gt; &lt;p&gt;There are of course other possible designs for and implementations of such a Create method.&amp;nbsp; An alternate implementation might look like this:&lt;/p&gt; &lt;blockquote&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Future&lt;/span&gt;&amp;lt;T&amp;gt; Create&amp;lt;T&amp;gt;(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;IAsyncResult&lt;/span&gt; iar, &lt;span style="color: #2b91af"&gt;Func&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;IAsyncResult&lt;/span&gt;, T&amp;gt; endFunc)&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;var&lt;/span&gt; f = &lt;span style="color: #2b91af"&gt;Future&lt;/span&gt;&amp;lt;T&amp;gt;.Create();&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ThreadPool&lt;/span&gt;.RegisterWaitForSingleObject(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; iar.AsyncWaitHandle, &lt;span style="color: blue"&gt;delegate &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;try&lt;/span&gt; { f.Value = endFunc(iar); }&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;catch&lt;/span&gt; (&lt;span style="color: #2b91af"&gt;Exception&lt;/span&gt; e) { f.Exception = e; }&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}, &lt;span style="color: blue"&gt;null&lt;/span&gt;, -1, &lt;span style="color: blue"&gt;true&lt;/span&gt;);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;return&lt;/span&gt; f;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;}&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Here's I'm using the same promise functionality of Future&amp;lt;T&amp;gt;, but instead of using the callback functionality of the APM, I'm relying on ThreadPool's RegisterWaitForSingleObject functionality.&amp;nbsp; When the provided IAsyncResult's AsyncWaitHandle is signaled (which will happen when the asynchronous operation completes), my delegate will be called to call endFunc and set the Future&amp;lt;T&amp;gt;'s Value or Exception property as shown previously.&amp;nbsp; This version can be used as follows:&lt;/p&gt; &lt;blockquote&gt; &lt;p class="MsoNormal"&gt;&lt;span style="font-size: 10pt; color: blue; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;var&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; readFuture = Create&amp;lt;&lt;span style="color: blue"&gt;int&lt;/span&gt;&amp;gt;(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; fs.BeginRead(buffer, 0, buffer.Length, &lt;span style="color: blue"&gt;null&lt;/span&gt;, &lt;span style="color: blue"&gt;null&lt;/span&gt;), &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; fs.EndRead);&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Now comes the interesting question...&lt;/p&gt; &lt;p&gt;We don't currently have a Create method like this on Future&amp;lt;T&amp;gt;.&amp;nbsp; You can write your own as has been shown here, but is this important enough for us to include one on Future&amp;lt;T&amp;gt; itself?&amp;nbsp; Do you have such a need in your applications?&amp;nbsp; Should we provide deeper support to further enable this kind of integration? Let us know :)&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8272833" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Task+Parallel+Library/default.aspx">Task Parallel Library</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/ThreadPool/default.aspx">ThreadPool</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Code+Samples/default.aspx">Code Samples</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Parallel+Extensions/default.aspx">Parallel Extensions</category></item><item><title>Ordering the output of parallel computations</title><link>http://blogs.msdn.com/pfxteam/archive/2008/03/11/8165836.aspx</link><pubDate>Wed, 12 Mar 2008 07:52:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8165836</guid><dc:creator>toub</dc:creator><slash:comments>11</slash:comments><comments>http://blogs.msdn.com/pfxteam/comments/8165836.aspx</comments><wfw:commentRss>http://blogs.msdn.com/pfxteam/commentrss.aspx?PostID=8165836</wfw:commentRss><wfw:comment>http://blogs.msdn.com/pfxteam/rsscomments.aspx?PostID=8165836</wfw:comment><description>&lt;P&gt;Frequently when attempting to do multiple operations in parallel, ordering becomes an issue.&amp;nbsp; Consider an application where I'm rendering and writing out to a video file frames of a movie:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P class=MsoNormal style="MARGIN-BOTTOM: 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;for&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; (&lt;SPAN style="COLOR: blue"&gt;int&lt;/SPAN&gt; i = 0; i &amp;lt; numberOfFrames; i++)&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;{&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;var&lt;/SPAN&gt; frame = GenerateFrame(i);&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;WriteToMovie(frame);&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;}&lt;/SPAN&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;For a bit of pizzazz, I'll show the same thing with LINQ:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P class=MsoNormal style="MARGIN-BOTTOM: 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;var&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; frames = &lt;SPAN style="COLOR: blue"&gt;from&lt;/SPAN&gt; i &lt;SPAN style="COLOR: blue"&gt;in&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;Enumerable&lt;/SPAN&gt;.Range(0, numberOfFrames)&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;select&lt;/SPAN&gt; GenerateFrame(i);&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; LINE-HEIGHT: 115%; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;foreach&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; (&lt;SPAN style="COLOR: blue"&gt;var&lt;/SPAN&gt; frame &lt;SPAN style="COLOR: blue"&gt;in&lt;/SPAN&gt; frames) WriteToMovie(frame);&lt;/SPAN&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Now, my GenerateFrame method is expensive and computationally intensive, so I'd like to generate frames in parallel. For this example, we'll assume that my GenerateFrame method is thread-safe and can be called concurrently (rendering one frame doesn't modify any state used to render another frame), but access to my WriteToMovie method must be serialized:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P class=MsoNormal style="MARGIN-BOTTOM: 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;using&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; (&lt;SPAN style="COLOR: #2b91af"&gt;ManualResetEvent&lt;/SPAN&gt; mre = &lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;ManualResetEvent&lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;false&lt;/SPAN&gt;))&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;{&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;int&lt;/SPAN&gt; count = numberOfFrames;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt; obj = &lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt;();&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;for&lt;/SPAN&gt; (&lt;SPAN style="COLOR: blue"&gt;int&lt;/SPAN&gt; i = 0; i &amp;lt; numberOfFrames; i++)&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ThreadPool&lt;/SPAN&gt;.QueueUserWorkItem(state =&amp;gt;&lt;SPAN style="COLOR: blue"&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;var&lt;/SPAN&gt; frame = GenerateFrame((&lt;FONT color=#0000ff&gt;int&lt;/FONT&gt;)state);&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; LINE-HEIGHT: 115%; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;lock&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;(obj) &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;WriteToMovie(frame);&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;?xml:namespace prefix = o /&gt;&lt;o:p&gt;&amp;nbsp;&lt;BR&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;if&lt;/SPAN&gt; (&lt;SPAN style="COLOR: #2b91af"&gt;Interlocked&lt;/SPAN&gt;.Decrement(&lt;SPAN style="COLOR: blue"&gt;ref&lt;/SPAN&gt; count) == 0) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mre.Set();&lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}, state);&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;mre.WaitOne();&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;}&lt;/SPAN&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Unfortunately, that's quite a bit of code overhead, and it also suffers from a fundamental ordering problem: the frames may end up being written to the output movie file in an arbitrary order, based on when the frame generation completes.&amp;nbsp; A version with this ordering issue fixed might look like the following:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P class=MsoNormal style="MARGIN-BOTTOM: 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;var&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; frames = &lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;Bitmap&lt;/SPAN&gt;[numberOfFrames];&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;var&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; events = (&lt;SPAN style="COLOR: blue"&gt;from&lt;/SPAN&gt; i &lt;SPAN style="COLOR: blue"&gt;in&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;Enumerable&lt;/SPAN&gt;.Range(0, numberOfFrames)&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;select&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;ManualResetEvent&lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;false&lt;/SPAN&gt;)).ToArray();&lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;for&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; (&lt;SPAN style="COLOR: blue"&gt;int&lt;/SPAN&gt; i = 0; i &amp;lt; numberOfFrames; i++)&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;{&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ThreadPool&lt;/SPAN&gt;.QueueUserWorkItem(state =&amp;gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;int&lt;/SPAN&gt; frameNum = (&lt;SPAN style="COLOR: blue"&gt;int&lt;/SPAN&gt;)state;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;frames[frameNum] = GenerateFrame(frameNum);&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;events[frameNum].Set();&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}, i);&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;}&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;BR&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;for&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; (&lt;SPAN style="COLOR: blue"&gt;int&lt;/SPAN&gt; i = 0; i &amp;lt; numberOfFrames; i++)&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;{&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;events[i].WaitOne();&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;WriteToMovie(frames[i]);&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;}&lt;/SPAN&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;This has the general effect I want, but there are still some unfortunately overheads here (for example, I'm creating, setting, and waiting on a ManualResetEvent per frame). It's also verbose.&amp;nbsp; Instead, I can use Future&amp;lt;T&amp;gt; from &lt;A href="http://msdn2.microsoft.com/en-us/concurrency/default.aspx" mce_href="http://msdn2.microsoft.com/en-us/concurrency/default.aspx"&gt;Parallel Extensions&lt;/A&gt; to solve the same problem:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P class=MsoNormal style="MARGIN-BOTTOM: 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;var&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; frames = (&lt;SPAN style="COLOR: blue"&gt;from&lt;/SPAN&gt; i &lt;SPAN style="COLOR: blue"&gt;in&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;Enumerable&lt;/SPAN&gt;.Range(0, numberOfFrames)&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;select&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;Future&lt;/SPAN&gt;.Create(() =&amp;gt; GenerateFrame(i))).&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ToArray();&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; LINE-HEIGHT: 115%; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;foreach&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; (&lt;SPAN style="COLOR: blue"&gt;var&lt;/SPAN&gt; frame &lt;SPAN style="COLOR: blue"&gt;in&lt;/SPAN&gt; frames) WriteToMovie(frame.Value);&lt;/SPAN&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;I love how close this is to the original LINQ version (and how much less code it is the than my previous ThreadPool sample).&amp;nbsp; Rather than selecting GenerateFrame(i), I'm selecting Future.Create(() =&amp;gt; GenerateFrame(i)), and rather than calling WriteToMovie(frame), I'm calling WriteToMovie(frame.Value).&amp;nbsp; With those changes, the frames are now being computed in parallel (note I'm also using ToArray to calls the entire query to be enumerated), and they're being written out to the movie file in the correct order without having to do any explicit locking or coordination.&amp;nbsp; Sweet!&lt;/P&gt;
&lt;P&gt;If I wanted to, I could do the same thing without LINQ, tracking the collection of futures explicitly:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P class=MsoNormal style="MARGIN-BOTTOM: 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;var&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; frames = &lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;Queue&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;Future&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;Bitmap&lt;/SPAN&gt;&amp;gt;&amp;gt;();&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;for&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; (&lt;SPAN style="COLOR: blue"&gt;int&lt;/SPAN&gt; i = 0; i &amp;lt; numberOfFrames; i++)&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;var&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; &lt;/SPAN&gt;num = i;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;frames.Enqueue(&lt;SPAN style="COLOR: #2b91af"&gt;Future&lt;/SPAN&gt;.Create(() =&amp;gt; GenerateFrame(num)));&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;}&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; LINE-HEIGHT: 115%; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;while&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; (frames.Count &amp;gt; 0) WriteToMovie(frames.Dequeue().Value);&lt;/SPAN&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;I could also use PLINQ:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P class=MsoNormal style="MARGIN-BOTTOM: 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;var&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; frames = &lt;SPAN style="COLOR: blue"&gt;from&lt;/SPAN&gt; i &lt;SPAN style="COLOR: blue"&gt;in&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;Enumerable&lt;/SPAN&gt;.Range(0, numberOfFrames).&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; AsParallel(&lt;SPAN style="COLOR: #2b91af"&gt;ParallelQueryOptions&lt;/SPAN&gt;.PreserveOrdering)&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;select&lt;/SPAN&gt; GenerateFrame(i);&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; LINE-HEIGHT: 115%; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;foreach&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; (&lt;SPAN style="COLOR: blue"&gt;var&lt;/SPAN&gt; frame &lt;SPAN style="COLOR: blue"&gt;in&lt;/SPAN&gt; frames) WriteToMovie(frame);&lt;/SPAN&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Three different approaches to solving the same problem with Parallel Extensions, and all of them requiring less code (and less complicated code) than my ThreadPool example.&amp;nbsp; Just makes you smile, doesn't it? :)&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8165836" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/pfxteam/archive/tags/PLINQ/default.aspx">PLINQ</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Task+Parallel+Library/default.aspx">Task Parallel Library</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/ThreadPool/default.aspx">ThreadPool</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Parallelism+Blockers/default.aspx">Parallelism Blockers</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Code+Samples/default.aspx">Code Samples</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Parallel+Extensions/default.aspx">Parallel Extensions</category></item><item><title>Custom parallel looping constructs</title><link>http://blogs.msdn.com/pfxteam/archive/2008/02/27/7919786.aspx</link><pubDate>Wed, 27 Feb 2008 19:25:35 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7919786</guid><dc:creator>toub</dc:creator><slash:comments>9</slash:comments><comments>http://blogs.msdn.com/pfxteam/comments/7919786.aspx</comments><wfw:commentRss>http://blogs.msdn.com/pfxteam/commentrss.aspx?PostID=7919786</wfw:commentRss><wfw:comment>http://blogs.msdn.com/pfxteam/rsscomments.aspx?PostID=7919786</wfw:comment><description>&lt;p&gt;For those of you that have examined the internals of the Task Parallel Library in our December '07 CTP release, you've likely noticed that the methods on the System.Threading.Parallel type are implemented on top of System.Threading.Tasks.Task type, and that they do so taking advantage of Task's self-replicating functionality.&amp;nbsp; The idea behind replication is that the Task will make just enough copies of itself as is necessary to ensure that all available processing cores are saturated with work.&amp;nbsp; This is useful not only for the Parallel constructs we implement, but also for custom loop constructs that you might want to implement for your own needs.&amp;nbsp; We're providing what we believe to be the most commonly desired constructs, but we're also quite aware that there will be plenty more than we can provide that will be useful.&lt;/p&gt; &lt;p&gt;As an example, we don't currently provide a parallel while construct, but one could easily be built on top of Task.&amp;nbsp; Consider a typical while loop:&lt;/p&gt; &lt;blockquote&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; color: blue; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;while&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; (condition()) &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;body();&lt;br&gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Here, body is executed over and over while condition is true; when condition is false, the loop exits.&amp;nbsp; We can create a parallel loop that behaves very much like this, but running on all available processing cores.&amp;nbsp; How might we do so?&amp;nbsp; First, let's try with the ThreadPool:&lt;/p&gt; &lt;blockquote&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; color: blue; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;public&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; ParallelWhile(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;Func&lt;/span&gt;&amp;lt;&lt;span style="color: blue"&gt;bool&lt;/span&gt;&amp;gt; condition, &lt;span style="color: #2b91af"&gt;Action&lt;/span&gt; body)&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;int&lt;/span&gt; n = &lt;span style="color: #2b91af"&gt;Environment&lt;/span&gt;.ProcessorCount;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;int&lt;/span&gt; count = n;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;?xml:namespace prefix = o /&gt;&lt;o:p&gt;&amp;nbsp;&lt;br&gt;&lt;br&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;using&lt;/span&gt; (&lt;span style="color: #2b91af"&gt;ManualResetEvent&lt;/span&gt; mre = &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;ManualResetEvent&lt;/span&gt;(&lt;span style="color: blue"&gt;false&lt;/span&gt;))&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;WaitCallback&lt;/span&gt; wc = &lt;span style="color: blue"&gt;delegate&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;while&lt;/span&gt; (condition()) &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;body();&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (&lt;span style="color: #2b91af"&gt;Interlocked&lt;/span&gt;.Decrement(&lt;span style="color: blue"&gt;ref&lt;/span&gt; count) == 0)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;mre.Set();&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;};&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;for&lt;/span&gt; (&lt;span style="color: blue"&gt;int&lt;/span&gt; i = 0; i &amp;lt; n; i++)&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (i == n - 1) wc(&lt;span style="color: blue"&gt;null&lt;/span&gt;);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;else&lt;/span&gt; &lt;span style="color: #2b91af"&gt;ThreadPool&lt;/span&gt;.QueueUserWorkItem(wc);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;mre.WaitOne();&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;}&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Certainly not an infeasible amount of code to write, but there are some difficulties here, and the implementation is not as efficient as one might like.&amp;nbsp; We can implement a similar construct with the Task Parallel Library:&lt;/p&gt; &lt;blockquote&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; color: blue; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;public&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; ParallelWhile(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;Func&lt;/span&gt;&amp;lt;&lt;span style="color: blue"&gt;bool&lt;/span&gt;&amp;gt; condition, &lt;span style="color: #2b91af"&gt;Action&lt;/span&gt; body)&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Task&lt;/span&gt;.Create(&lt;span style="color: blue"&gt;delegate &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;{&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;while&lt;/span&gt; (condition()) body(); &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;}, &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="color: #2b91af"&gt;TaskCreationOptions&lt;/span&gt;.SelfReplicating).Wait();&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;}&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Here, there's significantly less boilerplate necessary, and many of the potential performance issues with the previous example are addressed by the underlying library (or at least will be by the final release; there are performance issues with the current CTP, but that's all part of the beauty of a technology preview ;).&amp;nbsp; &lt;/p&gt; &lt;p&gt;Now, neither of these completely duplicates the semantics of the sequential while loop, which might be fine, but you might also have special requirements for how you want the loop to function.&amp;nbsp; As an example, in the sequential implementation, once condition returns false, no additional invocations of body will occur, even if another call to condition would return true; that's not the case with this parallel implementation.&amp;nbsp; Imagine this were running on four threads: one thread could see condition return false and exit the loop, but other threads could see condition return true and continue on (e.g. the condition delegate randomly returns true or false).&amp;nbsp; If those semantics were important to us, we could allow such information to be communicated between multiple iterations of the loop, at the expense of some volatile reads and writes:&lt;/p&gt; &lt;blockquote&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; color: blue; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;private&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af"&gt;VolatileBool&lt;/span&gt; {&amp;nbsp; &lt;span style="color: blue"&gt;public&lt;/span&gt; &lt;span style="color: blue"&gt;volatile&lt;/span&gt; &lt;span style="color: blue"&gt;bool&lt;/span&gt; Value; }&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; color: blue; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;public&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; ParallelWhile(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;Func&lt;/span&gt;&amp;lt;&lt;span style="color: blue"&gt;bool&lt;/span&gt;&amp;gt; condition, &lt;span style="color: #2b91af"&gt;Action&lt;/span&gt; body)&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;VolatileBool&lt;/span&gt; shouldExit = &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;VolatileBool&lt;/span&gt;();&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Task&lt;/span&gt;.Create(&lt;span style="color: blue"&gt;delegate&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;while&lt;/span&gt; (!shouldExit.Value &amp;amp;&amp;amp; condition()) body();&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;shouldExit.Value = &lt;span style="color: blue"&gt;true&lt;/span&gt;;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}, &lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;TaskCreationOptions&lt;/span&gt;.SelfReplicating).Wait();&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p class="MsoNormal"&gt;&lt;o:p&gt;Now when one iteration sees condition return false, it'll signal to all other threads that they should stop as soon as possible, such that even if condition returned true, they should exit before starting their next iteration.&amp;nbsp; As another example, if one iteration in the sequential implementation throws an exception, no additional iterations will start; while we can't mimic that entirely in the parallel implementation, as with the previous example we can at least signal to other threads that they should bail as soon as possible:&lt;/o:p&gt;&lt;/p&gt; &lt;blockquote&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; color: blue; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;private&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af"&gt;VolatileBool&lt;/span&gt; { &lt;span style="color: blue"&gt;public&lt;/span&gt; &lt;span style="color: blue"&gt;volatile&lt;/span&gt; &lt;span style="color: blue"&gt;bool&lt;/span&gt; Value; }&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; color: blue; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;public&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; ParallelWhile(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;Func&lt;/span&gt;&amp;lt;&lt;span style="color: blue"&gt;bool&lt;/span&gt;&amp;gt; condition, &lt;span style="color: #2b91af"&gt;Action&lt;/span&gt; body)&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;VolatileBool&lt;/span&gt; shouldExit = &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;VolatileBool&lt;/span&gt;();&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Task&lt;/span&gt;.Create(&lt;span style="color: blue"&gt;delegate&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;try&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;while&lt;/span&gt; (!shouldExit.Value &amp;amp;&amp;amp; condition()) body();&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;finally&lt;/span&gt; { shouldExit.Value = &lt;span style="color: blue"&gt;true&lt;/span&gt;; }&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}, &lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;TaskCreationOptions&lt;/span&gt;.SelfReplicating).Wait();&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;}&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Again, not a lot of code, but a fairly complete implementation (a few things remain, like validating that the arguments to the method are not null).&lt;/p&gt; &lt;p&gt;When would a parallel while loop like this be useful?&amp;nbsp; Consider a problem where you might use a heuristic such as simulated annealing to approximate the best result.&amp;nbsp; You might have, say, five seconds to find the best result, and thus you might run the heuristic over and over as many times as you can within that five seconds looking for the best possible answer.&amp;nbsp; With multiple cores, you could run this over and over in parallel, and for that a ParallelWhile construct like the one we just created would be very handy:&lt;/p&gt; &lt;blockquote&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; color: blue; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;object&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; monitor = &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: blue"&gt;object&lt;/span&gt;();&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; color: blue; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;double&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; bestResult = 0;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; color: #2b91af; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;DateTime&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; endTime = &lt;span style="color: #2b91af"&gt;DateTime&lt;/span&gt;.UtcNow.AddSeconds(5);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;ParallelWhile(() =&amp;gt; &lt;span style="color: #2b91af"&gt;DateTime&lt;/span&gt;.UtcNow &amp;lt; endTime, &lt;span style="color: blue"&gt;delegate&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;double&lt;/span&gt; result = SimulatedAnnealing();&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;lock&lt;/span&gt; (monitor) &lt;span style="color: blue"&gt;if&lt;/span&gt; (result &amp;gt; bestResult) bestResult = result;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;});&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p class="MsoNormal"&gt;&lt;o:p&gt;We can't provide all possible variations of looping constructs that all customers will be interested in.&amp;nbsp; We do, however, want to provide the lower-level mechanisms that will making building custom parallel loop implementations easy.&amp;nbsp; If you have comments or suggestions, we'd really love to hear them.&lt;/o:p&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7919786" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Task+Parallel+Library/default.aspx">Task Parallel Library</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/ThreadPool/default.aspx">ThreadPool</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Code+Samples/default.aspx">Code Samples</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Parallel+Extensions/default.aspx">Parallel Extensions</category></item><item><title>Task Parallel Library on Channel 9</title><link>http://blogs.msdn.com/pfxteam/archive/2008/02/19/7804314.aspx</link><pubDate>Wed, 20 Feb 2008 01:38:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7804314</guid><dc:creator>toub</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/pfxteam/comments/7804314.aspx</comments><wfw:commentRss>http://blogs.msdn.com/pfxteam/commentrss.aspx?PostID=7804314</wfw:commentRss><wfw:comment>http://blogs.msdn.com/pfxteam/rsscomments.aspx?PostID=7804314</wfw:comment><description>&lt;P&gt;Charles from Channel 9 sat down with several of us from the&amp;nbsp;Parallel Computing Platform team&amp;nbsp;to discuss the Task Parallel Library component of Parallel Extensions.&amp;nbsp;A video of the conversation is&amp;nbsp;now available on Channel9: &lt;A href="http://channel9.msdn.com/Showpost.aspx?postid=384229"&gt;http://channel9.msdn.com/Showpost.aspx?postid=384229&lt;/A&gt;. We hope you like it, and as always, feedback is welcome and appreciated!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7804314" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Task+Parallel+Library/default.aspx">Task Parallel Library</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/ThreadPool/default.aspx">ThreadPool</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Parallelism+Blockers/default.aspx">Parallelism Blockers</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Parallel+Extensions/default.aspx">Parallel Extensions</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Media/default.aspx">Media</category></item><item><title>Recursion and Concurrency</title><link>http://blogs.msdn.com/pfxteam/archive/2008/01/31/7357135.aspx</link><pubDate>Thu, 31 Jan 2008 22:55:27 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7357135</guid><dc:creator>toub</dc:creator><slash:comments>19</slash:comments><comments>http://blogs.msdn.com/pfxteam/comments/7357135.aspx</comments><wfw:commentRss>http://blogs.msdn.com/pfxteam/commentrss.aspx?PostID=7357135</wfw:commentRss><wfw:comment>http://blogs.msdn.com/pfxteam/rsscomments.aspx?PostID=7357135</wfw:comment><description>&lt;p&gt;When&amp;nbsp;teaching recursion in an introductory computer science course, one of the most common examples used involves a tree data structure.&amp;nbsp; Trees are useful in this regard as they are simple and recursive in nature, with a tree's children also being trees, and allow for teaching different kinds of traversals (in-order, pre-order, post-order, level-order, and so forth).&amp;nbsp; But when these introductory concepts meet multithreading, the concepts are no longer so simple, at least not with the tools available in mainstream languages today like C#, C++, and Java. Consider a simple Tree data structure:&lt;/p&gt; &lt;blockquote&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; color: blue; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;class&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; &lt;span style="color: #2b91af"&gt;Tree&lt;/span&gt;&amp;lt;T&amp;gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;public&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Tree&lt;/span&gt;&amp;lt;T&amp;gt; Left, Right; &lt;/span&gt;&lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;// children&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;public&lt;/span&gt; T Data; &lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;// data for this node&amp;nbsp;&lt;/span&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;}&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Let's say we want to execute an Action&amp;lt;T&amp;gt; for each datum stored in the tree, and let's assume I don't care about order (introducing parallelism could be questionable if I did).&amp;nbsp; That's straightforward to do sequentially and recursively:&lt;/p&gt; &lt;blockquote&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; color: blue; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;public&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; Process&amp;lt;T&amp;gt;(&lt;span style="color: #2b91af"&gt;Tree&lt;/span&gt;&amp;lt;T&amp;gt; tree, &lt;span style="color: #2b91af"&gt;Action&lt;/span&gt;&amp;lt;T&amp;gt; action)&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (tree == &lt;span style="color: blue"&gt;null&lt;/span&gt;) &lt;span style="color: blue"&gt;return&lt;/span&gt;;&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;//&amp;nbsp;Process the current node, then the left,&amp;nbsp;then the right&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;action(tree.Data);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Process(tree.Left, action);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Process(tree.Right, action);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;}&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;I could also do so without recursion by maintaining&amp;nbsp;an explicit stack (or queue, or some other data structure with different ordering guarantees):&lt;/p&gt; &lt;blockquote&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; color: blue; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;public&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; Process&amp;lt;T&amp;gt;(&lt;span style="color: #2b91af"&gt;Tree&lt;/span&gt;&amp;lt;T&amp;gt; tree, &lt;span style="color: #2b91af"&gt;Action&lt;/span&gt;&amp;lt;T&amp;gt; action)&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (tree == &lt;span style="color: blue"&gt;null&lt;/span&gt;) &lt;span style="color: blue"&gt;return&lt;/span&gt;;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;var&lt;/span&gt; toExplore = &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Stack&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Tree&lt;/span&gt;&amp;lt;T&amp;gt;&amp;gt;();&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;//&amp;nbsp;Start with the root node&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;toExplore.Push(tree);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;while&lt;/span&gt; (toExplore.Count &amp;gt; 0)&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;//&amp;nbsp;Grab the next node, process it, and push its children&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;var&lt;/span&gt; current = toExplore.Pop();&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;action(current.Data);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;span style="color: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if&lt;/span&gt; (current.Left != &lt;span style="color: blue"&gt;null&lt;/span&gt;) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;toExplore.Push(current.Left);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;span style="color: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if&lt;/span&gt; (current.Right != &lt;span style="color: blue"&gt;null&lt;/span&gt;) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;toExplore.Push(current.Right);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;}&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p class="MsoNormal"&gt;&lt;?xml:namespace prefix = o /&gt;&lt;o:p&gt;Now, let's assume the action we're performing on each node of the tree is independent, relatively expensive and/or that the tree is relatively large, and as such we want to process the tree in parallel (we're of course also assuming that the action delegate is thread-safe), meaning that we want multiple threads each running the action delegate on distinct tree nodes.&amp;nbsp; How do we do this with what we have in .NET today?&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;o:p&gt;There are multiple approaches, some more valid than others.&amp;nbsp; The first thing someone might try is to follow the original recursive implementation but using the ThreadPool, which could look something like this:&lt;/o:p&gt;&lt;/p&gt; &lt;blockquote&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; color: blue; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;public&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; Process&amp;lt;T&amp;gt;(&lt;span style="color: #2b91af"&gt;Tree&lt;/span&gt;&amp;lt;T&amp;gt; tree, &lt;span style="color: #2b91af"&gt;Action&lt;/span&gt;&amp;lt;T&amp;gt; action)&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (tree == &lt;span style="color: blue"&gt;null&lt;/span&gt;) &lt;span style="color: blue"&gt;return&lt;/span&gt;;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;//&amp;nbsp;Use an event to prevent this method from&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // returning until its children have completed&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;using&lt;/span&gt; (&lt;span style="color: blue"&gt;var &lt;/span&gt;mre = &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;ManualResetEvent&lt;/span&gt;(&lt;span style="color: blue"&gt;false&lt;/span&gt;))&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;//&amp;nbsp;Process the left&amp;nbsp;child asynchronously&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ThreadPool&lt;/span&gt;.QueueUserWorkItem(&lt;span style="color: blue"&gt;delegate&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Process(tree.Left, action);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;mre.Set();&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;});&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;//&amp;nbsp;Process current node and right child synchronously&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;action(tree.Data);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Process(tree.Right, action);&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;//&amp;nbsp;Wait for the left child&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;mre.WaitOne();&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;}&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p class="MsoNormal"&gt;&lt;o:p&gt;The idea behind this implementation is to, given a node, spin up a work item to process that node's left child in parallel with the current node, and then process the current node's data as well as its right child.&amp;nbsp; Of course, I could be losing out on some parallelism here as I delay processing of the right child until I'm done processing the current data.&amp;nbsp; So we modify it slightly:&lt;/o:p&gt;&lt;/p&gt; &lt;blockquote&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; color: blue; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;public&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; Process&amp;lt;T&amp;gt;(&lt;span style="color: #2b91af"&gt;Tree&lt;/span&gt;&amp;lt;T&amp;gt; tree, &lt;span style="color: #2b91af"&gt;Action&lt;/span&gt;&amp;lt;T&amp;gt; action)&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (tree == &lt;span style="color: blue"&gt;null&lt;/span&gt;) &lt;span style="color: blue"&gt;return&lt;/span&gt;;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;//&amp;nbsp;Use an event to wait for the children&lt;/span&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;using&lt;/span&gt; (&lt;span style="color: blue"&gt;var&lt;/span&gt; mre = &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;ManualResetEvent&lt;/span&gt;(&lt;span style="color: blue"&gt;false&lt;/span&gt;))&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;int&lt;/span&gt; count = 2;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;//&amp;nbsp;Process the left child asynchronously&lt;/span&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ThreadPool&lt;/span&gt;.QueueUserWorkItem(&lt;span style="color: blue"&gt;delegate&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Process(tree.Left, action);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (&lt;span style="color: #2b91af"&gt;Interlocked&lt;/span&gt;.Decrement(&lt;span style="color: blue"&gt;ref&lt;/span&gt; count) == 0) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mre.Set();&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;});&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;//&amp;nbsp;Process the right child asynchronously&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ThreadPool&lt;/span&gt;.QueueUserWorkItem(&lt;span style="color: blue"&gt;delegate&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Process(tree.Right, action);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (&lt;span style="color: #2b91af"&gt;Interlocked&lt;/span&gt;.Decrement(&lt;span style="color: blue"&gt;ref&lt;/span&gt; count) == 0) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mre.Set();&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;});&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;//&amp;nbsp;Process the current node synchronously&lt;/span&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;action(tree.Data);&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;//&amp;nbsp;Wait for the children&lt;/span&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;mre.WaitOne();&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;}&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p class="MsoNormal"&gt;&lt;o:p&gt;I've now fixed that issue, such that both the left and the right children could potentially be processed in parallel with the current node, but that was by far not the worst problem.&amp;nbsp; For starters, I'm creating a ManualResetEvent for every node in the tree... that's expensive.&amp;nbsp; ManualResetEvent is a thin wrapper around a Win32 kernel event primitive, so creating one of these things requires kernel transitions, as does setting and waiting on one.&amp;nbsp; Next, every time I process a node, I block waiting for its children to complete.&amp;nbsp; And as the processing of a node (all but the root) is happening on a thread from the ThreadPool, I'm blocking ThreadPool threads.&amp;nbsp; If a ThreadPool thread gets blocked, the ThreadPool will need to inject additional threads in order to process the remaining work items, and thus this implementation will require approximately one thread from the pool per node in the tree.&amp;nbsp; That's a lot of threads!&amp;nbsp; And that carries with it some serious problems.&amp;nbsp; By default, a thread in .NET has a megabyte of stack space committed for it, so each thread burns a megabyte of (virtual) memory.&amp;nbsp; The ThreadPool also throttles the creation of additional threads, such that introducing a new thread (once the number of pool threads equals the number of processors) will take 500 ms.&amp;nbsp; For a tree of 250 nodes, that means its processing will take close to 2 minutes, purely for the overhead of creating threads, nevermind the actual processing of the nodes.&amp;nbsp; And worse, there is a maximum number of threads in the pool: in .NET, the ThreadPool has a limited number of threads, by default 25 per processor in .NET 1.x/2.0 and 250 per processor in .NET 2.0 SP1.&amp;nbsp; If the pool reaches the maximum, no new threads will be created, and thus this implementation could deadlock.&amp;nbsp; Parent nodes will be waiting for their child nodes to complete, but the child nodes can't be processed until their parent nodes complete and relinquish a thread from the pool to execute.&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;o:p&gt;Obviously, we need a better implementation. Next up, we can walk the tree sequentially, queuing up a work item in the pool for each node in the tree.&amp;nbsp; Here we take that approach based on the recursive implementation of a tree walk:&lt;/o:p&gt;&lt;/p&gt; &lt;blockquote&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; color: blue; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;public&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; Process&amp;lt;T&amp;gt;(&lt;span style="color: #2b91af"&gt;Tree&lt;/span&gt;&amp;lt;T&amp;gt; tree, &lt;span style="color: #2b91af"&gt;Action&lt;/span&gt;&amp;lt;T&amp;gt; action)&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (tree == &lt;span style="color: blue"&gt;null&lt;/span&gt;) &lt;span style="color: blue"&gt;return&lt;/span&gt;;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;//&amp;nbsp;Use an event to wait for all of the nodes to complete&lt;/span&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;using&lt;/span&gt; (&lt;span style="color: blue"&gt;var&lt;/span&gt; mre = &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;ManualResetEvent&lt;/span&gt;(&lt;span style="color: blue"&gt;false&lt;/span&gt;))&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;int&lt;/span&gt; count = 1;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;//&amp;nbsp;Recursive delegate to walk the tree&lt;/span&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Action&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Tree&lt;/span&gt;&amp;lt;T&amp;gt;&amp;gt; processNode = &lt;span style="color: blue"&gt;null&lt;/span&gt;;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;processNode = node =&amp;gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (node == &lt;span style="color: blue"&gt;null&lt;/span&gt;) &lt;span style="color: blue"&gt;return&lt;/span&gt;;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;//&amp;nbsp;Asynchronously&amp;nbsp;run the action on&amp;nbsp;the current node&lt;/span&gt;&lt;br&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Interlocked&lt;/span&gt;.Increment(&lt;span style="color: blue"&gt;ref&lt;/span&gt; count);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ThreadPool&lt;/span&gt;.QueueUserWorkItem(&lt;span style="color: blue"&gt;delegate&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;action(node.Data);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (&lt;span style="color: #2b91af"&gt;Interlocked&lt;/span&gt;.Decrement(&lt;span style="color: blue"&gt;ref&lt;/span&gt; count) == 0) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mre.Set();&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;});&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;//&amp;nbsp;Process the&amp;nbsp;children&lt;/span&gt;&lt;br&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;processNode(node.Left);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;processNode(node.Right);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;};&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;//&amp;nbsp;Start off with the root node&lt;/span&gt;&lt;br&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;processNode(tree);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;//&amp;nbsp;Signal that no&amp;nbsp;more&amp;nbsp;work items will be created&lt;/span&gt;&lt;br&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (&lt;span style="color: #2b91af"&gt;Interlocked&lt;/span&gt;.Decrement(&lt;span style="color: blue"&gt;ref&lt;/span&gt; count) == 0) mre.Set();&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;//&amp;nbsp;Wait for all of the work to complete&lt;/span&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;mre.WaitOne();&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;}&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p class="MsoNormal"&gt;&lt;o:p&gt;This implementation is better from a resources perspective and won't lead to the same kind of deadlocks as in the previous example.&amp;nbsp; We're still creating a work item for each node, but now the work item is simply to asynchronously execute the action on the node's data, whereas the tree walk itself is still happening sequentially on the main thread (taking advantage of a recursive delegate).&amp;nbsp; To maintain blocking behavior&amp;nbsp;similar to&amp;nbsp;the previous examples (where the call to Process won't return until all of the work has completed) though not identical (the processing of children nodes don't block the parent), a counter is incremented before each work item is created and is decremented when each work item finishes; only when that counter reaches 0 will the main thread continue (note how we need to start the counter at 1 and then decrement it after all of the work items have been created... this is to ensure that a work item completing before all of the work has been kicked off doesn't set the event prematurely).&amp;nbsp; We can&amp;nbsp;take the same approach &lt;/o:p&gt;&lt;o:p&gt;with a variant of the iterative implementation shown earlier:&lt;/o:p&gt;&lt;/p&gt; &lt;blockquote&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; color: blue; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;public&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; Process&amp;lt;T&amp;gt;(&lt;span style="color: #2b91af"&gt;Tree&lt;/span&gt;&amp;lt;T&amp;gt; tree, &lt;span style="color: #2b91af"&gt;Action&lt;/span&gt;&amp;lt;T&amp;gt; action)&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (tree == &lt;span style="color: blue"&gt;null&lt;/span&gt;) &lt;span style="color: blue"&gt;return&lt;/span&gt;;&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;Use an event to wait for all of the nodes&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // to complete&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;using&lt;/span&gt; (&lt;span style="color: blue"&gt;var &lt;/span&gt;mre = &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;ManualResetEvent&lt;/span&gt;(&lt;span style="color: blue"&gt;false&lt;/span&gt;))&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;int&lt;/span&gt; count = 1;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;//&amp;nbsp;Start with the root node&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue"&gt;var&lt;/span&gt; toExplore = &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Stack&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Tree&lt;/span&gt;&amp;lt;T&amp;gt;&amp;gt;();&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;toExplore.Push(tree);&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;//&amp;nbsp;Process all of the nodes&lt;/span&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;while&lt;/span&gt; (toExplore.Count &amp;gt; 0)&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;//&amp;nbsp;Get the current node and and push its children&lt;/span&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;var&lt;/span&gt; current = toExplore.Pop();&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;span style="color: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&lt;/span&gt; (current.Left != &lt;span style="color: blue"&gt;null&lt;/span&gt;) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;toExplore.Push(current.Left);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;span style="color: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if&lt;/span&gt; (current.Right != &lt;span style="color: blue"&gt;null&lt;/span&gt;)&amp;nbsp;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;toExplore.Push(current.Right);&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;//&amp;nbsp;Asynchronously process the&amp;nbsp;data&lt;/span&gt;&lt;br&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #2b91af"&gt;Interlocked&lt;/span&gt;.Increment(&lt;span style="color: blue"&gt;ref&lt;/span&gt; count);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ThreadPool&lt;/span&gt;.QueueUserWorkItem(&lt;span style="color: blue"&gt;delegate&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;action(current.Data);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (&lt;span style="color: #2b91af"&gt;Interlocked&lt;/span&gt;.Decrement(&lt;span style="color: blue"&gt;ref&lt;/span&gt; count) == 0) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mre.Set();&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;});&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;//&amp;nbsp;Signal that no more work items will&amp;nbsp;be created&lt;/span&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (&lt;span style="color: #2b91af"&gt;Interlocked&lt;/span&gt;.Decrement(&lt;span style="color: blue"&gt;ref&lt;/span&gt; count) == 0) mre.Set();&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;//&amp;nbsp;Wait for all work items to be completed&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;mre.WaitOne();&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p class="MsoNormal"&gt;&lt;o:p&gt;These approaches work by queueing a work item per node in the tree.&amp;nbsp; &lt;/o:p&gt;&lt;o:p&gt;There are, of course, other approaches.&amp;nbsp; Rather than adding a work item per node, we can create N work items, and have each work item process approximately 1/Nth of the nodes in the tree, where N is the number of threads.&amp;nbsp; For example, we could store all of the nodes into a list and then split that list into N pieces and have a work item process each piece:&lt;/o:p&gt;&lt;/p&gt; &lt;blockquote&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; color: blue; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;public&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; Process&amp;lt;T&amp;gt;(&lt;span style="color: #2b91af"&gt;Tree&lt;/span&gt;&amp;lt;T&amp;gt; tree, &lt;span style="color: #2b91af"&gt;Action&lt;/span&gt;&amp;lt;T&amp;gt; action)&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (tree == &lt;span style="color: blue"&gt;null&lt;/span&gt;) &lt;span style="color: blue"&gt;return&lt;/span&gt;;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;br&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;//&amp;nbsp;Create a list of all nodes in the tree&lt;/span&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;var&lt;/span&gt; nodes = &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Tree&lt;/span&gt;&amp;lt;T&amp;gt;&amp;gt;();&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;var&lt;/span&gt; toExplore = &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Stack&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Tree&lt;/span&gt;&amp;lt;T&amp;gt;&amp;gt;();&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;toExplore.Push(tree);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;while&lt;/span&gt; (toExplore.Count &amp;gt; 0)&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;var&lt;/span&gt; current = toExplore.Pop();&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;nodes.Add(current);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;span style="color: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if&lt;/span&gt; (current.Left != &lt;span style="color: blue"&gt;null&lt;/span&gt;)&amp;nbsp;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;toExplore.Push(current.Left);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;span style="color: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if&lt;/span&gt; (current.Right != &lt;span style="color: blue"&gt;null&lt;/span&gt;)&amp;nbsp;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;toExplore.Push(current.Right);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;//&amp;nbsp;Divide the list up into chunks&lt;/span&gt;&lt;br&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;int&lt;/span&gt; workItems = &lt;span style="color: #2b91af"&gt;Environment&lt;/span&gt;.ProcessorCount;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;int&lt;/span&gt; chunkSize = &lt;span style="color: #2b91af"&gt;Math&lt;/span&gt;.Max(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; nodes.Count / workItems, 1);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;int&lt;/span&gt; count = workItems;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;//&amp;nbsp;Use an event to wait for all work items&lt;/span&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;using&lt;/span&gt; (&lt;span style="color: #2b91af"&gt;&lt;span style="color: blue"&gt;var &lt;/span&gt;&lt;/span&gt;mre = &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;ManualResetEvent&lt;/span&gt;(&lt;span style="color: blue"&gt;false&lt;/span&gt;))&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;//&amp;nbsp;Each work item processes appx 1/Nth of the&amp;nbsp;data items&lt;/span&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;WaitCallback&lt;/span&gt; callback = state =&amp;gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;int&lt;/span&gt; iteration = (&lt;span style="color: blue"&gt;int&lt;/span&gt;)state;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;int&lt;/span&gt; from = chunkSize * iteration;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue"&gt;int&lt;/span&gt; &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;to = iteration == workItems - 1 ?&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; nodes.Count : &lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;chunkSize * (iteration + 1);&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;while&lt;/span&gt; (from &amp;lt; to) action(nodes[from++].Data);&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (&lt;span style="color: #2b91af"&gt;Interlocked&lt;/span&gt;.Decrement(&lt;span style="color: blue"&gt;ref&lt;/span&gt; count) == 0) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mre.Set();&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;};&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;//&amp;nbsp;The ThreadPool is&amp;nbsp;used to process all but one of the &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // chunks; the current thread is used for that chunk, &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // rather than just blocking.&lt;/span&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;for&lt;/span&gt; (&lt;span style="color: blue"&gt;int&lt;/span&gt; i = 0; i&amp;lt;workItems; i++)&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (i &amp;lt; workItems-1) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;ThreadPool&lt;/span&gt;.QueueUserWorkItem(callback, i);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;else&lt;/span&gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; callback(i);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;//&amp;nbsp;Wait for all work to complete&lt;/span&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;mre.WaitOne();&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;}&lt;/span&gt;&lt;/blockquote&gt; &lt;p class="MsoNormal"&gt;&lt;o:p&gt;Rather than statically dividing the work up, I could also rewrite the code such that each of the work items themselves is responsible for pulling work to handle:&lt;/o:p&gt;&lt;/p&gt; &lt;blockquote&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; color: blue; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;public&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; Process&amp;lt;T&amp;gt;(&lt;span style="color: #2b91af"&gt;Tree&lt;/span&gt;&amp;lt;T&amp;gt; tree, &lt;span style="color: #2b91af"&gt;Action&lt;/span&gt;&amp;lt;T&amp;gt; action)&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (tree == &lt;span style="color: blue"&gt;null&lt;/span&gt;) &lt;span style="color: blue"&gt;return&lt;/span&gt;;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;//&amp;nbsp;Get an enumerator for the tree&lt;/span&gt;&lt;br&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IEnumerator&lt;/span&gt;&amp;lt;T&amp;gt; enumerator = &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GetNodes(tree).GetEnumerator();&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;int&lt;/span&gt; workItems = &lt;span style="color: #2b91af"&gt;Environment&lt;/span&gt;.ProcessorCount;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;int&lt;/span&gt; count = workItems;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;//&amp;nbsp;Use an event to wait for all work&amp;nbsp;items &lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;to complete&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;using&lt;/span&gt; (&lt;span style="color: blue"&gt;var&lt;/span&gt; mre = &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;ManualResetEvent&lt;/span&gt;(&lt;span style="color: blue"&gt;false&lt;/span&gt;))&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;//&amp;nbsp;Each work item will continually pull data from the &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // enumerator and process it until there is no more data&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // to process&lt;/span&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;WaitCallback&lt;/span&gt; callback = &lt;span style="color: blue"&gt;delegate&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;while&lt;/span&gt; (&lt;span style="color: blue"&gt;true&lt;/span&gt;)&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;T data;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;lock&lt;/span&gt; (enumerator)&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (!enumerator.MoveNext())&lt;span style="color: blue"&gt; break&lt;/span&gt;;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;data = enumerator.Current;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;action(data);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (&lt;span style="color: #2b91af"&gt;Interlocked&lt;/span&gt;.Decrement(&lt;span style="color: blue"&gt;ref&lt;/span&gt; count) == 0)&amp;nbsp;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mre.Set();&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;};&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;br&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;//&amp;nbsp;The ThreadPool is&amp;nbsp;used to process all but one of the &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // chunks; the current&amp;nbsp; thread is used for that chunk,&amp;nbsp;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// rather than just blocking.&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;o:p&gt;&lt;br&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;for&lt;/span&gt; (&lt;span style="color: blue"&gt;int&lt;/span&gt; i = 0; i &amp;lt; workItems; i++)&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (i &amp;lt; workItems-1)&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ThreadPool&lt;/span&gt;.QueueUserWorkItem(&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;callback, i);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;else&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;callback(i);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;//&amp;nbsp;Wait for all work to complete&lt;/span&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;mre.WaitOne();&lt;/span&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;}&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;o:p&gt;&lt;br&gt;&lt;span style="font-size: 10pt; color: green; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;//&amp;nbsp;An enumerator for a tree&lt;/span&gt;&lt;br&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; color: blue; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;public&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: #2b91af"&gt;IEnumerable&lt;/span&gt;&amp;lt;T&amp;gt; GetNodes&amp;lt;T&amp;gt;(&lt;span style="color: #2b91af"&gt;Tree&lt;/span&gt;&amp;lt;T&amp;gt; tree)&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (tree != &lt;span style="color: blue"&gt;null&lt;/span&gt;)&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;yield&lt;/span&gt; &lt;span style="color: blue"&gt;return&lt;/span&gt; tree.Data;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;foreach&lt;/span&gt; (&lt;span style="color: blue"&gt;var&lt;/span&gt; data &lt;span style="color: blue"&gt;in&lt;/span&gt; GetNodes(tree.Left))&amp;nbsp;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue"&gt;yield&lt;/span&gt; &lt;span style="color: blue"&gt;return&lt;/span&gt; data;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;foreach&lt;/span&gt; (&lt;span style="color: blue"&gt;var&lt;/span&gt; data &lt;span style="color: blue"&gt;in&lt;/span&gt; GetNodes(tree.Right))&amp;nbsp;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="color: blue"&gt;yield&lt;/span&gt; &lt;span style="color: blue"&gt;return&lt;/span&gt; data;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;}&lt;/span&gt;&lt;/blockquote&gt; &lt;p class="MsoNormal"&gt;Here I use a C# iterator to create an enumerator for all of the nodes in the tree.&amp;nbsp; A work item is queued for each processor, and each of those work items retrieves an item from the enumerator, processes it, and goes back for more.&amp;nbsp; Since multiple threads are accessing the enumerator (which isn't thread-safe), retrieving an item from it must be done under lock.&amp;nbsp; Unfortunately, that's expensive; a better implementation would shift to grabbing more items from the enumerator so that the lock could be taken fewer times.&lt;/p&gt; &lt;p class="MsoNormal"&gt;There are still further possible approaches.&amp;nbsp; For example, we could walk the tree until we get to nodes of a certain depth (such as the log of the number of cores) and then process all of the subtrees at that depth in parallel with each other.&lt;/p&gt; &lt;p class="MsoNormal"&gt;All of these implementations also have potential locality issues.&amp;nbsp; It's reasonable to assume (though certainly not guaranteed) that nodes in the tree near to each other were created near to each other in time and are likely near to each other in memory (this assumption may be more applicable to other recursive problems, such as ones to be discussed shortly).&amp;nbsp; For best cache performance, we'd like to try to have nodes near each other processed by the same thread and near to each other in time so that cache hits are optimized.&amp;nbsp; But all of these solutions have been, in effect, randomly assigning nodes to threads.&lt;/p&gt; &lt;p class="MsoNormal"&gt;Once of the nice things about the tree walk example is that it's very simple; there are no pre- or post- processing steps necessary for a node, which means I don't actually need to block at the end of a parent in order to wait for its children as I did in some of the previous examples.&amp;nbsp; The problem also allows me to start processing children of a node before I've finished processing its parent.&amp;nbsp; Many recursive problems are not like that, however.&amp;nbsp; Consider a typical recursive sort, like quick sort:&lt;/p&gt; &lt;blockquote&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; color: blue; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;public&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; Quicksort&amp;lt;T&amp;gt;(T[] arr, &lt;span style="color: blue"&gt;int&lt;/span&gt; left, &lt;span style="color: blue"&gt;int&lt;/span&gt; right)&amp;nbsp;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue"&gt;where&lt;/span&gt; T : &lt;span style="color: #2b91af"&gt;IComparable&lt;/span&gt;&amp;lt;T&amp;gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (right &amp;gt; left)&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;int&lt;/span&gt; pivot = Partition(arr, left, right);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Quicksort(arr, left, pivot - 1);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Quicksort(arr, pivot + 1, right);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;}&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p class="MsoNormal"&gt;Order here definitely makes a difference.&amp;nbsp; If we think of the Partition step like the execution of the Action in the tree walk example, I'm not able to do the Partition in parallel with the processing of the children, since the processing of the children is dependent on the outcome of the call to Partition.&amp;nbsp; That's a pretty easy problem to workaround of course; I just wouldn't start the children executing asynchronously until after the Partition step is complete.&amp;nbsp; But now consider a recursive sort like merge sort:&lt;/p&gt; &lt;blockquote&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; color: blue; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;public&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; Mergesort&amp;lt;T&amp;gt;(T[] arr, &lt;span style="color: blue"&gt;int&lt;/span&gt; left, &lt;span style="color: blue"&gt;int&lt;/span&gt; right)&amp;nbsp;&lt;span style="color: blue"&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; where&lt;/span&gt; T : &lt;span style="color: #2b91af"&gt;IComparable&lt;/span&gt;&amp;lt;T&amp;gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (right &amp;gt; left)&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;int&lt;/span&gt; mid = (right + left) / 2;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Mergesort(arr, left, mid);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Mergesort(arr, mid + 1, right);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Merge(arr, left, mid + 1, right);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;}&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p class="MsoNormal"&gt;The merge step at a particular node must occur after the recursive calls, which means in a parallel implementation either we'd need to block waiting for the two recursive calls to complete before starting the call to Merge, or we'd have to use a form of continuation-passing style to join on the two merge calls and have their completion start the execution of the merge operation.&amp;nbsp; Either way, this kind of processing with the ThreadPool is incredibly tricky to implement efficiently.&lt;/p&gt; &lt;p class="MsoNormal"&gt;One of our goals when designing Parallel Extensions to the .NET Framework was to make such recursive parallel operations much easier to implement, and much easier to implement efficiently.&lt;/p&gt; &lt;p class="MsoNormal"&gt;Let's start with PLINQ and our tree walk.&amp;nbsp; Taking the Tree&amp;lt;T&amp;gt; iterator we already implemented, processing the tree in parallel is now a cakewalk:&lt;/p&gt; &lt;blockquote&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; color: blue; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;public&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; Process&amp;lt;T&amp;gt;(&lt;span style="color: #2b91af"&gt;Tree&lt;/span&gt;&amp;lt;T&amp;gt; tree, &lt;span style="color: #2b91af"&gt;Action&lt;/span&gt;&amp;lt;T&amp;gt; action)&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (tree == &lt;span style="color: blue"&gt;null&lt;/span&gt;) &lt;span style="color: blue"&gt;return&lt;/span&gt;;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;GetNodes(tree).AsParallel().ForAll(action);&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;}&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p class="MsoNormal"&gt;&lt;o:p&gt;Under the covers, this is very much like our implementation where we created several work items, and each of those work items pulled items (under lock) from the&amp;nbsp;enumerator.&amp;nbsp; PLINQ is more efficient, however, and uses varying chunk sizes&amp;nbsp;(rather than always pulling just one element at a time) in an attempt to minimize the number of times the lock must be taken,&amp;nbsp;hopefully reducing contention on the lock.&amp;nbsp; This, of course, as with the similar previous implementation is doing a sequential tree walk but running the actions in parallel.&amp;nbsp; If we actually want&amp;nbsp;to walk the tree in parallel, we can use the Task Parallel Library:&lt;/o:p&gt;&lt;/p&gt; &lt;blockquote&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; color: blue; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;public&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; Process&amp;lt;T&amp;gt;(&lt;span style="color: #2b91af"&gt;Tree&lt;/span&gt;&amp;lt;T&amp;gt; tree, &lt;span style="color: #2b91af"&gt;Action&lt;/span&gt;&amp;lt;T&amp;gt; action)&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (tree == &lt;span style="color: blue"&gt;null&lt;/span&gt;) &lt;span style="color: blue"&gt;return&lt;/span&gt;;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Parallel&lt;/span&gt;.Do(&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;() =&amp;gt; action(tree.Data),&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;() =&amp;gt; Process(tree.Left, action),&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;() =&amp;gt; Process(tree.Right, action));&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;}&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p class="MsoNormal"&gt;&lt;o:p&gt;It's almost scary how simple that is.&amp;nbsp; The Parallel.Do statement potentially runs the three provided operations in parallel, blocking until all three have completed.&amp;nbsp; A really cool thing about this though is that it will attempt to reuse the current thread as much as possible, so we don't run into the same kinds of issues that we had with the ThreadPool where we were blocking a whole slew of ThreadPool threads.&amp;nbsp; The underlying work-stealing nature of the implementation also goes a long way towards helping to address the cache locality issues we previously mentioned.&amp;nbsp; If we want more control, we can dive down below the Parallel class and explicitly use Tasks:&lt;/o:p&gt;&lt;/p&gt; &lt;blockquote&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; color: blue; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font size="2"&gt;public&lt;/font&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font size="2"&gt; &lt;/font&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;&lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; Process&amp;lt;T&amp;gt;(&lt;span style="color: #2b91af"&gt;Tree&lt;/span&gt;&amp;lt;T&amp;gt; tree, &lt;span style="color: #2b91af"&gt;Action&lt;/span&gt;&amp;lt;T&amp;gt; action)&lt;br&gt;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font size="2"&gt;{&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font size="2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (tree == &lt;span style="color: blue"&gt;null&lt;/span&gt;) &lt;span style="color: blue"&gt;return&lt;/span&gt;;&lt;br&gt;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font size="2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;&lt;span style="color: blue"&gt;var&lt;/span&gt; t1 = &lt;span style="color: #2b91af"&gt;Task&lt;/span&gt;.Create(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue"&gt;delegate&lt;/span&gt; { Process(tree.Left, action); });&lt;br&gt;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font size="2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;&lt;span style="color: blue"&gt;var&lt;/span&gt; t2 = &lt;span style="color: #2b91af"&gt;Task&lt;/span&gt;.Create(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue"&gt;delegate&lt;/span&gt; { Process(tree.Right, action); });&lt;br&gt;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font size="2"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;action(tree.Data);&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;font size="2"&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;font color="#000000"&gt;&lt;span style="color: #2b91af"&gt;Task&lt;/span&gt;.WaitAll(&lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Task&lt;/span&gt;[] { t1, t2 });&lt;/font&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;}&lt;/span&gt;&lt;/font&gt;&lt;/blockquote&gt; &lt;p class="MsoNormal"&gt;&lt;o:p&gt;The same techniques can apply to the quicksort implementation:&lt;/o:p&gt;&lt;/p&gt; &lt;blockquote&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; color: blue; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font size="2"&gt;public&lt;/font&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font size="2"&gt; &lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; Quicksort&amp;lt;T&amp;gt;(T[] arr, &lt;span style="color: blue"&gt;int&lt;/span&gt; left, &lt;span style="color: blue"&gt;int&lt;/span&gt; right) &lt;span style="color: blue"&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; where&lt;/span&gt; T : &lt;span style="color: #2b91af"&gt;IComparable&lt;/span&gt;&amp;lt;T&amp;gt;&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font size="2"&gt;{&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font size="2"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (right &amp;gt; left)&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font size="2"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font size="2"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;int&lt;/span&gt; pivot = Partition(arr, left, right);&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font size="2"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Parallel&lt;/span&gt;.Do(&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font size="2"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;() =&amp;gt; Quicksort(arr, left, pivot - 1),&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font size="2"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;() =&amp;gt; Quicksort(arr, pivot + 1, right));&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;font size="2"&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;}&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p class="MsoNormal"&gt;&lt;o:p&gt;as well as to the mergesort implementation:&lt;/o:p&gt;&lt;/p&gt; &lt;blockquote&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; color: blue; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font size="2"&gt;public&lt;/font&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font size="2"&gt; &lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; Mergesort&amp;lt;T&amp;gt;(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; T[] arr, &lt;span style="color: blue"&gt;int&lt;/span&gt; left, &lt;span style="color: blue"&gt;int&lt;/span&gt; right)&amp;nbsp;&lt;/font&gt;&lt;span style="color: blue"&gt;&lt;font size="2"&gt;where&lt;/font&gt;&lt;/span&gt;&lt;font size="2"&gt; T : &lt;span style="color: #2b91af"&gt;IComparable&lt;/span&gt;&amp;lt;T&amp;gt;&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font size="2"&gt;{&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font size="2"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (right &amp;gt; left)&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font size="2"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font size="2"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;int&lt;/span&gt; mid = (right + left) / 2;&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font size="2"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Parallel&lt;/span&gt;.Do(&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font size="2"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;() =&amp;gt; Mergesort(arr, left, mid),&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font size="2"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;() =&amp;gt; Mergesort(arr, mid + 1, right));&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font size="2"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Merge(arr, left, mid + 1, right);&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;font size="2"&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;}&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p class="MsoNormal"&gt;&lt;o:p&gt;I love how simple the parallelization of this code becomes.&amp;nbsp; However, this code still has some issues.&amp;nbsp; There is necessary overhead to an operation like Parallel.Do, which under the covers creates Tasks for the individual operations and waits on those Tasks; that overhead may not be a big deal if the work being done is significant, but for fine-grain concurrency that overhead can end up dominating the computation, potentially causing the parallel implementation to run slower than the sequential implementation.&amp;nbsp; For now, the best way to work around that is to complicate the code slightly with thresholds.&amp;nbsp; The idea behind a threshold is that you introduce enough parallelism to keep the system saturated, but once enough has been expressed, you switch over to a sequential implementation so as to avoid the extra overhead.&amp;nbsp; With the tree walk, using a depth as a threshold might look like this:&lt;/o:p&gt;&lt;/p&gt; &lt;blockquote&gt; &lt;p class="MsoNormal"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;span style="font-size: 10pt; color: blue; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font size="2"&gt;private&lt;/font&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font size="2"&gt; &lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; Process&amp;lt;T&amp;gt;(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;Tree&lt;/span&gt;&amp;lt;T&amp;gt; tree, &lt;span style="color: #2b91af"&gt;Action&lt;/span&gt;&amp;lt;T&amp;gt; action, &lt;span style="color: blue"&gt;int&lt;/span&gt; depth)&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font size="2"&gt;{&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font size="2"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (tree == &lt;span style="color: blue"&gt;null&lt;/span&gt;) &lt;span style="color: blue"&gt;return&lt;/span&gt;;&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font size="2"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (depth &amp;gt; 5)&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font size="2"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font size="2"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;action(tree.Data);&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font size="2"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Process(tree.Left, action, depth + 1);&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font size="2"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Process(tree.Right, action, depth + 1);&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font size="2"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font size="2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;&lt;font size="2"&gt;else&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font size="2"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font size="2"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Parallel&lt;/span&gt;.Do(&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font size="2"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;() =&amp;gt; action(tree.Data),&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font size="2"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;() =&amp;gt; Process(tree.Left, action, depth + 1),&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;font size="2"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;() =&amp;gt; Process(tree.Right, action, depth + 1));&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;font size="2"&gt;&lt;span style="font-size: 10pt; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; font-family: consolas; mso-bidi-font-family: 'Times New Roman'; mso-no-proof: yes"&gt;}&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p class="MsoNormal"&gt;&lt;o:p&gt;I have both a sequential and a parallel implementation here, and I switch from one to the other based on how deep in the tree I am.&amp;nbsp; Depth may not always be the right gating factor to use as a threshold, especially if the tree isn't balanced.&amp;nbsp; We're working through ways to reduce the overhead we currently see for these operations in the early CTP we released in December, and we're testing out some approaches that may eliminate the need to use thresholds in certain cases.&amp;nbsp; For now, though, as you're playing around with the bits, keep thresholds in mind.&amp;nbsp; The same technique could be used with both sorting examples, as well.&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;o:p&gt;All in all, parallelism is&amp;nbsp;a very interesting problem when it comes to recursion, and we hope the Parallel Extensions to the .NET Framework go a long way towards making the merging of these two concepts significantly easier.&lt;/o:p&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7357135" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/pfxteam/archive/tags/PLINQ/default.aspx">PLINQ</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Task+Parallel+Library/default.aspx">Task Parallel Library</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/ThreadPool/default.aspx">ThreadPool</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Parallelism+Blockers/default.aspx">Parallelism Blockers</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Code+Samples/default.aspx">Code Samples</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Parallel+Extensions/default.aspx">Parallel Extensions</category></item></channel></rss>