<?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>Recursion and Concurrency</title><link>http://blogs.msdn.com/pfxteam/archive/2008/01/31/7357135.aspx</link><description>When teaching recursion in an introductory computer science course, one of the most common examples used involves a tree data structure. Trees are useful in this regard as they are simple and recursive in nature, with a tree's children also being trees,</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>MSDN Blog Postings  &amp;raquo; Recursion and Concurrency</title><link>http://blogs.msdn.com/pfxteam/archive/2008/01/31/7357135.aspx#7359718</link><pubDate>Fri, 01 Feb 2008 01:02:21 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7359718</guid><dc:creator>MSDN Blog Postings  » Recursion and Concurrency</dc:creator><description>&lt;p&gt;PingBack from &lt;a rel="nofollow" target="_new" href="http://msdnrss.thecoderblogs.com/2008/01/31/recursion-and-concurrency-2/"&gt;http://msdnrss.thecoderblogs.com/2008/01/31/recursion-and-concurrency-2/&lt;/a&gt;&lt;/p&gt;
</description></item><item><title>MSDN Blog Postings  &amp;raquo; Recursion and Concurrency</title><link>http://blogs.msdn.com/pfxteam/archive/2008/01/31/7357135.aspx#7359721</link><pubDate>Fri, 01 Feb 2008 01:02:30 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7359721</guid><dc:creator>MSDN Blog Postings  » Recursion and Concurrency</dc:creator><description>&lt;p&gt;PingBack from &lt;a rel="nofollow" target="_new" href="http://msdnrss.thecoderblogs.com/2008/01/31/recursion-and-concurrency/"&gt;http://msdnrss.thecoderblogs.com/2008/01/31/recursion-and-concurrency/&lt;/a&gt;&lt;/p&gt;</description></item><item><title>re: Recursion and Concurrency</title><link>http://blogs.msdn.com/pfxteam/archive/2008/01/31/7357135.aspx#7366624</link><pubDate>Fri, 01 Feb 2008 07:28:39 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7366624</guid><dc:creator>Wei Lu</dc:creator><description>&lt;p&gt;Nice one, Actually I did some similar work (&lt;a rel="nofollow" target="_new" href="http://portal.acm.org/citation.cfm?id=1272462"&gt;http://portal.acm.org/citation.cfm?id=1272462&lt;/a&gt;) for the parallel XML processing in C#, which is mainly about the parallel DOM tree traversal. The thread is keeping traversing the tree by manipulating a stack just like the sequential algorithm does, but other threads, when out of work, can steal the work from the bottom of the stack. I think your solution based on the Task has the same effect. &lt;/p&gt;
&lt;p&gt;Also controlling the depth of the parallel traversal is exactly right, my experiments show that it is key to the performance win of the parallel xml processing.&lt;/p&gt;
</description></item><item><title>re: Recursion and Concurrency</title><link>http://blogs.msdn.com/pfxteam/archive/2008/01/31/7357135.aspx#7369453</link><pubDate>Fri, 01 Feb 2008 10:22:47 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7369453</guid><dc:creator>toub</dc:creator><description>&lt;p&gt;Cool, thanks for the link and information.&lt;/p&gt;
</description></item><item><title>re: Recursion and Concurrency</title><link>http://blogs.msdn.com/pfxteam/archive/2008/01/31/7357135.aspx#7379230</link><pubDate>Sat, 02 Feb 2008 00:57:47 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7379230</guid><dc:creator>Chris Mullins</dc:creator><description>&lt;p&gt;Great article! I love the work you guys are doing with this, and am looking forward to a solid concurrency framework! &lt;/p&gt;
&lt;p&gt;I have a question though: In one section, you mention that creating and waiting on Wait Handles requires a (sometimes) unacceptable number of kernel transistions. &lt;/p&gt;
&lt;p&gt;... how does Task.WaitAll (that you reference later in the document) avoid this? Are you using a user-mode wait object in there, and each task enlists in that, or does this mechanism suffer the same issues with Wait handle creation and use? &lt;/p&gt;
</description></item><item><title>re: Recursion and Concurrency</title><link>http://blogs.msdn.com/pfxteam/archive/2008/01/31/7357135.aspx#7380080</link><pubDate>Sat, 02 Feb 2008 03:23:53 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7380080</guid><dc:creator>toub</dc:creator><description>&lt;p&gt;Thanks, Chris. Task.WaitAll can, in effect, just wait on each Task in sequence. &amp;nbsp;In many situations, waiting on a Task that hasn't started yet will actually cause the Task to be executed inline, rather than blocking waiting for it to complete execution on another thread. &amp;nbsp;In addition, even if we do need to do a true wait, we may spin a bit in user-mode first.&lt;/p&gt;
</description></item><item><title>Récursif &amp; parallèle...</title><link>http://blogs.msdn.com/pfxteam/archive/2008/01/31/7357135.aspx#7439712</link><pubDate>Mon, 04 Feb 2008 18:39:46 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7439712</guid><dc:creator>Pierrick's Blog</dc:creator><description>&lt;p&gt;un excellent article de l' &amp;#233;quipe PFX (Parallel Framework), sur comment parall&amp;#232;liser un algorithme r&amp;#233;cursif&lt;/p&gt;
</description></item><item><title>re: Recursion and Concurrency</title><link>http://blogs.msdn.com/pfxteam/archive/2008/01/31/7357135.aspx#7749623</link><pubDate>Sun, 17 Feb 2008 13:33:07 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7749623</guid><dc:creator>Yury Serdyuk</dc:creator><description>&lt;p&gt;Synchronization mechanism based on counters and events is very complicated and hard especially for non-qualified programmers.&lt;/p&gt;
&lt;p&gt;Some proof of that is that the author overlooked some simplification in the code below:&lt;/p&gt;
&lt;p&gt;public static void Process&amp;lt;T&amp;gt;(Tree&amp;lt;T&amp;gt; tree, Action&amp;lt;T&amp;gt; action)&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;if (tree == null) return;&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;// Use an event to wait for all of the nodes to complete&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;using (var mre = new ManualResetEvent(false))&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;{&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;//int count = 1;&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;int count = 0; &amp;nbsp; // NOTE THIS !!!&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;// Recursive delegate to walk the tree&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Action&amp;lt;Tree&amp;lt;T&amp;gt;&amp;gt; processNode = null;&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;processNode = node =&amp;gt;&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;if (node == null) return;&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;// Asynchronously run the action on the current node&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Interlocked.Increment(ref count);&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;ThreadPool.QueueUserWorkItem(delegate&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;action(node.Data);&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;if (Interlocked.Decrement(ref count) == 0) &lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;mre.Set();&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;});&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;// Process the children&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;processNode(node.Left);&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;processNode(node.Right);&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;};&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;// Start off with the root node&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;processNode(tree);&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;// Signal that no more work items will be created&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;//if (Interlocked.Decrement(ref count) == 0)&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; //mre.Set(); &amp;nbsp;WE CAN DROP GIVEN STATEMENT !!!&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;// Wait for all of the work to complete&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;mre.WaitOne();&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;}&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;For synchronization purposes more transparent and easy are so called &amp;quot;chords&amp;quot; costructions &lt;/p&gt;
&lt;p&gt;(see languages as Polyphonic C#, COmega, MC#(www.mcsharp.net)).&lt;/p&gt;
</description></item><item><title>re: Recursion and Concurrency</title><link>http://blogs.msdn.com/pfxteam/archive/2008/01/31/7357135.aspx#7806942</link><pubDate>Wed, 20 Feb 2008 04:02:12 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7806942</guid><dc:creator>toub</dc:creator><description>&lt;p&gt;Yury, thanks, but that is not a valid simplification. Let's say the count did begin at 0, as you suggest. &amp;nbsp;We then kick off a work item to process the first node; before doing so, we increment the count to 1, and after doing so, we decrement the count and check whether it's now 0, setting the ManualResetEvent if it is. &amp;nbsp;Now, let's say the tree has 500 nodes in it, but we end up finishing the first work item before we even get to the pre-increment for the second work item. &amp;nbsp;The completion of the first item sets the event, and now Process will not wait for all of the nodes to complete before exiting. &amp;nbsp;That's why I initialize the count to 1 and then decrement it after all of the work items have been queued, so that I can be sure Process will wait for all items to complete before returning.&lt;/p&gt;
&lt;p&gt;As an aside, I appreciate your passion around your MC# language, but please stop replying to our forum threads and blog posts plugging it. &amp;nbsp;We certainly welcome your contributions on both the forums and blog comments, as it seems like you have a lot to contribute, but please keep your posts relevant to Parallel Extensions; for example, if there are constructs you think would be useful for us to add, please do let us know. &amp;nbsp;Thanks!&lt;/p&gt;
</description></item><item><title>re: Recursion and Concurrency</title><link>http://blogs.msdn.com/pfxteam/archive/2008/01/31/7357135.aspx#7836877</link><pubDate>Thu, 21 Feb 2008 15:56:28 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7836877</guid><dc:creator>Yury Serdyuk</dc:creator><description>&lt;p&gt;&amp;gt;The completion of the first item sets the event, and &amp;gt;now Process will not wait for all of the nodes to &amp;gt;complete before exiting. &lt;/p&gt;
&lt;p&gt;No, it's impossible because the initial call&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; processNode(tree);&lt;/p&gt;
&lt;p&gt;can't be completed ( and so we can't move to check&lt;/p&gt;
&lt;p&gt;mre.WaitOne(); ) until &lt;/p&gt;
&lt;p&gt; &amp;nbsp; Interlocked.Increment(ref count);&lt;/p&gt;
&lt;p&gt;has been performed for all nodes of the tree.&lt;/p&gt;
</description></item><item><title>re: Recursion and Concurrency</title><link>http://blogs.msdn.com/pfxteam/archive/2008/01/31/7357135.aspx#7843793</link><pubDate>Fri, 22 Feb 2008 04:52:13 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7843793</guid><dc:creator>toub</dc:creator><description>&lt;p&gt;No, it's not impossible. &amp;nbsp;Here's the sequence of events:&lt;/p&gt;
&lt;p&gt;1) We call Process() on the root node. &amp;nbsp;The count is 0.&lt;/p&gt;
&lt;p&gt;2) We call Interlocked.Increment on count, increasing it to 1, and we queue a work item.&lt;/p&gt;
&lt;p&gt;3) Before the main thread that's iterating over the nodes moves on to queue a work item for the next node, the work item for the first node executes and does an Interlocked.Decrement on count, setting count to 0. &amp;nbsp;It sees that count is 0, and sets the event.&lt;/p&gt;
&lt;p&gt;4) The main thread continues to queue work items for the rest of the nodes.&lt;/p&gt;
&lt;p&gt;5) When it's done queueing work items, it waits on the event. &amp;nbsp;But at this point, even though all of the work items may not have completed, the event has already been set (by the completion of the first work item).&lt;/p&gt;
</description></item><item><title>re: Recursion and Concurrency</title><link>http://blogs.msdn.com/pfxteam/archive/2008/01/31/7357135.aspx#7846963</link><pubDate>Fri, 22 Feb 2008 14:32:20 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7846963</guid><dc:creator>Yury Serdyuk</dc:creator><description>&lt;p&gt;Yes, you are right.&lt;/p&gt;
&lt;p&gt;Nevertheless, this subtle issue shows&lt;/p&gt;
&lt;p&gt;that a programmer needs more simple and transparent&lt;/p&gt;
&lt;p&gt;synchronization constucts/tools.&lt;/p&gt;
</description></item><item><title>re: Recursion and Concurrency</title><link>http://blogs.msdn.com/pfxteam/archive/2008/01/31/7357135.aspx#7875998</link><pubDate>Sun, 24 Feb 2008 14:35:06 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7875998</guid><dc:creator>Yury Serdyuk</dc:creator><description>&lt;p&gt;Please, one more question.&lt;/p&gt;
&lt;p&gt;Does the Parallel.Do uses ThreadPool to run the provided operations?&lt;/p&gt;
&lt;p&gt;In any case, how the deadlock possibility is avoided in that case?&lt;/p&gt;
&lt;p&gt;To my view, the method &lt;/p&gt;
&lt;p&gt;public static void Process&amp;lt;T&amp;gt;(Tree&amp;lt;T&amp;gt; tree, Action&amp;lt;T&amp;gt; action)&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;if (tree == null) return;&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;Parallel.Do(&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;() =&amp;gt; action(tree.Data),&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;() =&amp;gt; Process(tree.Left, action),&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;() =&amp;gt; Process(tree.Right, action));&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;is an abbreviation of (prone to deadlocks) &lt;/p&gt;
&lt;p&gt;public static void Process&amp;lt;T&amp;gt;(Tree&amp;lt;T&amp;gt; tree, Action&amp;lt;T&amp;gt; action)&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;if (tree == null) return;&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;// Use an event to wait for the children&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;using (var mre = new ManualResetEvent(false))&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;{&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;int count = 2;&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;// Process the left child asynchronously&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;ThreadPool.QueueUserWorkItem(delegate&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Process(tree.Left, action);&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;if (Interlocked.Decrement(ref count) == 0) &lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;mre.Set();&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;});&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;// Process the right child asynchronously&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;ThreadPool.QueueUserWorkItem(delegate&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Process(tree.Right, action);&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;if (Interlocked.Decrement(ref count) == 0) &lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;mre.Set();&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;});&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;// Process the current node synchronously&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;action(tree.Data);&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;// Wait for the children&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;mre.WaitOne();&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;}&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;Thanks.&lt;/p&gt;
</description></item><item><title>re: Recursion and Concurrency</title><link>http://blogs.msdn.com/pfxteam/archive/2008/01/31/7357135.aspx#7881660</link><pubDate>Sun, 24 Feb 2008 22:28:40 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7881660</guid><dc:creator>toub</dc:creator><description>&lt;p&gt;Good question. &amp;nbsp;No, Parallel.Do does not use the ThreadPool. &amp;nbsp;Under the covers, it uses a work-stealing pool implementation (which will be further revamped significantly for future preview releases; coding there is already well underway). &amp;nbsp;When you wait on a task, if that task has already started running, yes, the current thread will block waiting on the task on an event similar to how I've done in my ThreadPool recursive walk. &amp;nbsp;But, if the task has not already started executing (which will be the case most of the time), in most cases the task will actually be executed inline; in other words, rather than waiting for the task to complete elsewhere, the thread that would be waiting for another thread to start and finish the task instead simply executes it. &amp;nbsp;As such, you don't end up in the same deadlock situation as with the ThreadPool, since pool threads aren't being blocked for every node.&lt;/p&gt;
</description></item><item><title>re: Recursion and Concurrency</title><link>http://blogs.msdn.com/pfxteam/archive/2008/01/31/7357135.aspx#7902122</link><pubDate>Tue, 26 Feb 2008 14:09:38 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7902122</guid><dc:creator>Yury Serdyuk</dc:creator><description>&lt;p&gt;Many thanks, but, if you please, another question&lt;/p&gt;
&lt;p&gt;concerning the replicable tasks in TPL.&lt;/p&gt;
&lt;p&gt;In the paper&lt;/p&gt;
&lt;p&gt;&lt;a rel="nofollow" target="_new" href="http://msdn.microsoft.com/msdnmag/issues/07/10/Futures/default.aspx?loc=en"&gt;http://msdn.microsoft.com/msdnmag/issues/07/10/Futures/default.aspx?loc=en&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;there is the following example of using of replicable task (in fact, it's a Parallel.For implementation):&lt;/p&gt;
&lt;p&gt;static void For( int from, int to, Action&amp;lt;int&amp;gt; body )&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt; &amp;nbsp;int index = from;&lt;/p&gt;
&lt;p&gt; &amp;nbsp;ReplicableTask rtask = new ReplicableTask( delegate {&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;int i;&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;while ((i = Interlocked.Increment(ref index)-1) &amp;lt; to) {&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp;body(i);&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;}&lt;/p&gt;
&lt;p&gt; &amp;nbsp;});&lt;/p&gt;
&lt;p&gt; &amp;nbsp;rtask.Wait();&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;Lets look on the body of given method more abstractly as&lt;/p&gt;
&lt;p&gt;int index = from;&lt;/p&gt;
&lt;p&gt;ReplicableTask rtask = new ReplicableTask( delegate {&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;int i;&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;F ( i, index ); &amp;nbsp;// &amp;nbsp;some function &lt;/p&gt;
&lt;p&gt;});&lt;/p&gt;
&lt;p&gt;or even as&lt;/p&gt;
&lt;p&gt;ReplicableTask rtask = new ReplicableTask( delegate {&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;lt;delagate body&amp;gt; &amp;nbsp; &lt;/p&gt;
&lt;p&gt;});&lt;/p&gt;
&lt;p&gt;The quiestion is -&lt;/p&gt;
&lt;p&gt;how many (ordinary) Tasks ( i.e., action delegates running in other threads) will be created to perform &lt;/p&gt;
&lt;p&gt;given Replicable task?&lt;/p&gt;
&lt;p&gt;In other words, what's a criterion which bounds a Task generation?&lt;/p&gt;
&lt;p&gt;Thanks.&lt;/p&gt;
</description></item><item><title>re: Recursion and Concurrency</title><link>http://blogs.msdn.com/pfxteam/archive/2008/01/31/7357135.aspx#7919831</link><pubDate>Wed, 27 Feb 2008 19:31:25 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7919831</guid><dc:creator>toub</dc:creator><description>&lt;p&gt;We're currently reworking the implementation of replicating tasks to make them simpler and more efficient. &amp;nbsp;However, the basic idea is that we'll create as few as we can while still ensuring that all of the virtual processors for the relevant TaskManager are able to have a replica if they need one to remain busy.&lt;/p&gt;
</description></item><item><title>re: Recursion and Concurrency</title><link>http://blogs.msdn.com/pfxteam/archive/2008/01/31/7357135.aspx#9349168</link><pubDate>Tue, 20 Jan 2009 20:36:30 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9349168</guid><dc:creator>Wei Lu</dc:creator><description>&lt;p&gt;Stephen, If we use PLINQ (i.e., GetNodes(tree).AsParallel().ForAll(action);) for the parallel tree-wall, how does PLINQ internally work? will it work as your parallel recursive algorithm shown above, or it just flattens the tree in to a sequence of nodes for the linear partitioning to run action delegate? Thanks&lt;/p&gt;
</description></item><item><title>re: Recursion and Concurrency</title><link>http://blogs.msdn.com/pfxteam/archive/2008/01/31/7357135.aspx#9353942</link><pubDate>Wed, 21 Jan 2009 05:03:14 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9353942</guid><dc:creator>toub</dc:creator><description>&lt;p&gt;In effect, that code will flatten the tree, passing to AsParallel the IEnumerable&amp;lt;Node&amp;gt; containing all of the nodes from the tree to be processed. &amp;nbsp;We are planning to support the ability to provide your own custom partitioning scheme, such that you could more efficiently traverse a tree-like data structure if you chose to, but that functionality doesn't show up in the CTPs we've released thus far.&lt;/p&gt;
</description></item><item><title>re: Recursion and Concurrency</title><link>http://blogs.msdn.com/pfxteam/archive/2008/01/31/7357135.aspx#9354488</link><pubDate>Wed, 21 Jan 2009 06:54:21 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9354488</guid><dc:creator>Wei Lu</dc:creator><description>&lt;p&gt;Thanks for the answer. Actually your recursive code has shown a very nature/dynamic partitions on the tree structure if we view the TPL and PLINQ in an integrated way. That is when one thread is traversing the tree, the rightmost sub-tree will be at the bottom of the stack. Since in TPL the thief always steal the task from the bottom (correct me if I am wrong), the thief thread will get the rightmost sub-tree while the owner thread is working on the left-most one. &lt;/p&gt;
</description></item></channel></rss>