<?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 : Beta</title><link>http://blogs.msdn.com/pfxteam/archive/tags/Beta/default.aspx</link><description>Tags: Beta</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>What's New in Beta 2 for PLINQ</title><link>http://blogs.msdn.com/pfxteam/archive/2009/11/05/9918226.aspx</link><pubDate>Thu, 05 Nov 2009 20:37:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9918226</guid><dc:creator>essey</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/pfxteam/comments/9918226.aspx</comments><wfw:commentRss>http://blogs.msdn.com/pfxteam/commentrss.aspx?PostID=9918226</wfw:commentRss><wfw:comment>http://blogs.msdn.com/pfxteam/rsscomments.aspx?PostID=9918226</wfw:comment><description>&lt;P style="MARGIN: 0in 0in 0pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;&lt;SPAN style="mso-bidi-font-weight: bold"&gt;Included in the .NET 4 Framework Beta 2&lt;/SPAN&gt;&lt;SPAN style="COLOR: #1f497d"&gt; &lt;/SPAN&gt;is a&lt;SPAN style="COLOR: #1f497d"&gt; &lt;/SPAN&gt;more robust and faster version of PLINQ.&amp;nbsp; Between B1 and B2, PLINQ changes have mainly been under the covers, so hopefully no need to rewrite any of your applications to see the improvements. &lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt" class=MsoNormal&gt;&lt;o:p&gt;&lt;FONT size=3 face=Calibri&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT: -0.25in; MARGIN: 0in 0in 0pt 0.5in; mso-list: l0 level1 lfo1" class=MsoListParagraph&gt;&lt;SPAN style="mso-fareast-font-family: Calibri"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3 face=Calibri&gt;1.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;Many improvements to performance and scalability&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT: -0.25in; MARGIN: 0in 0in 0pt 0.5in; mso-list: l0 level1 lfo1" class=MsoListParagraph&gt;&lt;SPAN style="mso-fareast-font-family: Calibri"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3 face=Calibri&gt;2.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;GroupBy and GroupJoin now preserve&lt;SPAN style="COLOR: #1f497d"&gt; &lt;/SPAN&gt;ordering within the groups&lt;SPAN style="COLOR: #1f497d"&gt; &lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT: -0.25in; MARGIN: 0in 0in 0pt 0.5in; mso-list: l0 level1 lfo1" class=MsoListParagraph&gt;&lt;SPAN style="mso-fareast-font-family: Calibri"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3 face=Calibri&gt;3.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;Better integration with performance profiling, which now shows PLINQ markers&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT: -0.25in; MARGIN: 0in 0in 0pt 0.5in; mso-list: l0 level1 lfo1" class=MsoListParagraph&gt;&lt;SPAN style="mso-fareast-font-family: Calibri"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3 face=Calibri&gt;4.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;Cancellation consistently works across all PLINQ operators&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT: -0.25in; MARGIN: 0in 0in 0pt 0.5in; mso-list: l0 level1 lfo1" class=MsoListParagraph&gt;&lt;SPAN style="mso-fareast-font-family: Calibri"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3 face=Calibri&gt;5.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;Scoped some of the boundary conditions of PLINQ in .NET 4 in Beta2 of Parallel Extensions as follows: &amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT: -0.25in; MARGIN: 0in 0in 0pt 1in; mso-list: l0 level2 lfo1" class=MsoListParagraph&gt;&lt;SPAN style="mso-fareast-font-family: Calibri"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3 face=Calibri&gt;a.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;Max Degree of Parallelism changed from 64 to 63&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT: -0.25in; MARGIN: 0in 0in 0pt 1in; mso-list: l0 level2 lfo1" class=MsoListParagraph&gt;&lt;SPAN style="mso-bidi-font-weight: bold; mso-fareast-font-family: Calibri"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3 face=Calibri&gt;b.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="mso-bidi-font-weight: bold"&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;Greater consistency regarding maximum input length&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT: -1.5in; MARGIN: 0in 0in 0pt 1.5in; mso-list: l0 level3 lfo1; mso-text-indent-alt: -9.0pt" class=MsoListParagraph&gt;&lt;SPAN style="mso-bidi-font-weight: bold; mso-fareast-font-family: Calibri"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&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;&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;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;FONT size=3 face=Calibri&gt;i.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="mso-bidi-font-weight: bold"&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;PLINQ does not support inputs of length &amp;gt; Int32.MaxValue. Queries may throw OverflowException for many operators.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT: -1.5in; MARGIN: 0in 0in 0pt 1.5in; mso-list: l0 level3 lfo1; mso-text-indent-alt: -9.0pt" class=MsoListParagraph&gt;&lt;SPAN style="mso-bidi-font-weight: bold; mso-fareast-font-family: Calibri"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&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;&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;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;FONT size=3 face=Calibri&gt;ii.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="mso-bidi-font-weight: bold"&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;LongCount no longer counts beyond Int32.MaxValue&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT: -0.25in; MARGIN: 0in 0in 0pt 0.5in; mso-list: l0 level1 lfo1" class=MsoListParagraph&gt;&lt;SPAN style="mso-fareast-font-family: Calibri"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3 face=Calibri&gt;6.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;Improved robustness&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT: -0.25in; MARGIN: 0in 0in 0pt 1in; mso-list: l0 level2 lfo1" class=MsoListParagraph&gt;&lt;SPAN style="mso-fareast-font-family: Calibri"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3 face=Calibri&gt;a.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;Reliability and concurrency focus&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT: -0.25in; MARGIN: 0in 0in 0pt 1in; mso-list: l0 level2 lfo1" class=MsoListParagraph&gt;&lt;SPAN style="mso-fareast-font-family: Calibri"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3 face=Calibri&gt;b.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;More consistent exception handling and error model&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT: -0.25in; MARGIN: 0in 0in 0pt 0.5in; mso-list: l0 level1 lfo1" class=MsoListParagraph&gt;&lt;SPAN style="mso-fareast-font-family: Calibri"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3 face=Calibri&gt;7.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;Other bug fixes&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt" class=MsoNormal&gt;&lt;o:p&gt;&lt;FONT size=3 face=Calibri&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;If any of these severely impact your applications, particularly the boundary conditions, please let us know so that we can include that in our planning efforts.&amp;nbsp; For now, we found that it makes the most sense to scope some inputs and give a reliable and predictable experience in this release.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt" class=MsoNormal&gt;&lt;o:p&gt;&lt;FONT size=3 face=Calibri&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;Happy Coding!&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9918226" 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/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/Beta/default.aspx">Beta</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/.NET+4/default.aspx">.NET 4</category></item><item><title>What’s new in Beta 2 for the Task Parallel Library? (Part 3/3)</title><link>http://blogs.msdn.com/pfxteam/archive/2009/11/04/9917581.aspx</link><pubDate>Wed, 04 Nov 2009 21:52:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9917581</guid><dc:creator>dashih</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/pfxteam/comments/9917581.aspx</comments><wfw:commentRss>http://blogs.msdn.com/pfxteam/commentrss.aspx?PostID=9917581</wfw:commentRss><wfw:comment>http://blogs.msdn.com/pfxteam/rsscomments.aspx?PostID=9917581</wfw:comment><description>&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT face=Calibri&gt;&lt;FONT size=3&gt;Related posts:&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3 face=Calibri&gt;&lt;A title="What's new in Beta 2 for the Task Parallel Library? (1/3)" href="http://blogs.msdn.com/pfxteam/archive/2009/10/19/9909371.aspx" target=_blank mce_href="http://blogs.msdn.com/pfxteam/archive/2009/10/19/9909371.aspx"&gt;What's new in Beta 2 for the Task Parallel Library? (1/3)&lt;/A&gt;&lt;/FONT&gt;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3 face=Calibri&gt;&lt;A title="What's new in Beta 2 for the Task Parallel Library? (2/3)" href="http://blogs.msdn.com/pfxteam/archive/2009/10/27/9913610.aspx" target=_blank mce_href="http://blogs.msdn.com/pfxteam/archive/2009/10/27/9913610.aspx"&gt;What's new in Beta 2 for the Task Parallel Library? (2/3)&lt;/A&gt;&lt;/FONT&gt;&lt;/DIV&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;Last time, we covered Tasks being detached by default and some refactorings in our multiple-Task continuation APIs.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The final post of this series will discuss &lt;B style="mso-bidi-font-weight: normal"&gt;Nested Tasks and Unwrap&lt;/B&gt;, a &lt;B style="mso-bidi-font-weight: normal"&gt;Parallel namespace change&lt;/B&gt;, and some &lt;B style="mso-bidi-font-weight: normal"&gt;changes under the covers&lt;/B&gt;.&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;H2 style="MARGIN: 10pt 0in 0pt"&gt;&lt;FONT size=4&gt;&lt;FONT color=#4f81bd&gt;&lt;FONT face=Cambria&gt;Nested Tasks and Unwrap&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/H2&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;We’ve added the Unwrap APIs to address scenarios that deal with nested Tasks.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Before jumping into Unwrap, let’s first talk about nested Tasks, e.g. a Task&amp;lt;Task&amp;gt; or Task&amp;lt;Task&amp;lt;TResult&amp;gt;&amp;gt;.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For example:&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt 0.5in" class=MsoNormal&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;var nestedTask = Task.Factory.StartNew(() =&amp;gt;&lt;BR&gt;{&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;return Task.Factory.StartNew(() =&amp;gt;&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;BR&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;return 42;&lt;BR&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 class=arial9italic&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-STYLE: normal; FONT-SIZE: 9pt; mso-bidi-font-family: 'Times New Roman'; mso-bidi-font-size: 11.0pt"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;SPAN style="mso-bidi-font-family: Arial; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri"&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;Nested Tasks commonly lead to unexpected behavior in applications.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For example, consider an API that provides the following functionality for asynchronously logging into a web service (like one from Facebook), retrieving a list of friends, and sending an email to each friend.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;// Given a user name and password, returns a Task whose&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;// result is a UserToken object.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;public Task&amp;lt;UserToken&amp;gt; LogOn(string username, string password);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;// Given a UserToken, returns a Task whose result&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;// is a collection of Friend objects.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;public Task&amp;lt;FriendCollection&amp;gt; GetFriendList(UserToken userToken);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;// Given a Friend, subject, and body, returns a Task that&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;// represents an email sending operation.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;public Task SendEmail(Friend friend, string subject, string body);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;SPAN style="mso-bidi-font-family: Arial; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri"&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;A user would like to be able to write code like the following, utilizing these APIs and Task continuations:&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;var userToken = LogOn(user, pass);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;var friends = userToken.ContinueWith(_ =&amp;gt; &lt;B style="mso-bidi-font-weight: normal"&gt;GetFriendList(userToken.Result));&lt;/B&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;var emails = friends.ContinueWith(_ =&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;var sentMails = new List&amp;lt;Task&amp;gt;();&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;foreach(var friend in friends.Result)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&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;sentMails.Add(SendEmail(friend, subject, body));&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;return Task.Factory.ContinueWhenAll(&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&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;sentMails.ToArray(), tasks =&amp;gt; Task.WaitAll(tasks));&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;});&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;emails&lt;B style="mso-bidi-font-weight: normal"&gt;.ContinueWith&lt;/B&gt;(_ =&amp;gt; Console.WriteLine(“All emails sent”));&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;SPAN style="mso-bidi-font-family: Arial; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri"&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;The bolded code is problematic.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Because the GetFriendList method returns a Task&amp;lt;FriendCollection&amp;gt;, the ‘friends’ variable is actually going to be a Task&amp;lt;Task&amp;lt;FriendCollection&amp;gt;&amp;gt;.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This will cause a compiler error at the foreach loop, because ‘friends.Result’ will return a Task&amp;lt;FriendCollection&amp;gt; instead of a FriendCollection. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;The compiler error in this case is a good thing, of course, highlighting a programming error.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;However, once a developer realizes the type mismatch, he still has to code additional logic to unwrap the ‘friends’ Task so that it returns an actual FriendCollection.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This logic is nontrivial, especially if it is to correctly deal with exceptions, cancellation, etc.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The last line is also problematic.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The emails variable here is actually of type Task&amp;lt;Task&amp;gt;.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The outer Task will complete once the inner Task is returned from its body, even if the inner Task hasn’t completed.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The net result of this is that “All emails sent” could be written out prior to all of the email tasks actually completing.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;SPAN style="mso-bidi-font-family: Arial; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri"&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;Now, you may have noticed that, in Beta 1, we provided special ContinueWith overloads to deal with this type of scenario.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For example:&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;public Task&amp;lt;TResult&amp;gt; ContinueWith&amp;lt;TResult&amp;gt;(&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Func&amp;lt;Task, Task&amp;lt;TResult&amp;gt;&amp;gt; continuationFunction);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT face=Calibri&gt;&lt;FONT size=3&gt;The Func returns a Task&amp;lt;TResult&amp;gt;, so normally, ContinueWith would return a Task&amp;lt;Task&amp;lt;TResult&amp;gt;&amp;gt;.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But this ContinueWith overload does some magic under the covers to return a Task&amp;lt;TResult&amp;gt;.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;There were a number of reasons why we didn’t like this approach, including:&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT: -0.25in; MARGIN: 0in 0in 0pt 0.5in; mso-list: l0 level1 lfo2" class=MsoListParagraphCxSpFirst&gt;&lt;SPAN style="FONT-FAMILY: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;·&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Calibri&gt;&lt;FONT size=3&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Too much magic.&lt;/B&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It’s hard to explain why one set of ContinueWith overloads is “just different”.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT: -0.25in; MARGIN: 0in 0in 0pt 0.5in; mso-list: l0 level1 lfo2" class=MsoListParagraphCxSpMiddle&gt;&lt;SPAN style="FONT-FAMILY: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;·&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Calibri&gt;&lt;FONT size=3&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Only works for ContinueWith&lt;/B&gt;.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;What if user scenarios result in nested Tasks for other Task creation APIs like StartNew, ContinueWhenAll, etc.?&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT: -0.25in; MARGIN: 0in 0in 10pt 0.5in; mso-list: l0 level1 lfo2" class=MsoListParagraphCxSpLast&gt;&lt;SPAN style="FONT-FAMILY: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;·&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;What if nested Tasks are actually desired&lt;/B&gt;?&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/B&gt;If a user actually wants that Task&amp;lt;Task&amp;lt;TResult&amp;gt;&amp;gt;, he still might unknowingly bind to this magical overload.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;Given these reasons, our solution for Beta 2 and beyond is two Unwrap extension methods.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;namespace System.Threading.Tasks&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;public static class TaskExtensions&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&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;public static Task Unwrap(&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&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;&lt;/SPAN&gt;this Task&amp;lt;Task&amp;gt; task);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&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;public static Task&amp;lt;TResult&amp;gt; Unwrap&amp;lt;TResult&amp;gt;(&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&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;&lt;/SPAN&gt;this Task&amp;lt;Task&amp;lt;TResult&amp;gt;&amp;gt; task);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;These methods may be used to transform any Task&amp;lt;Task&amp;gt; or Task&amp;lt;Task&amp;lt;TResult&amp;gt;&amp;gt; into a Task or Task&amp;lt;TResult&amp;gt;, respectively.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The transformation performed produces a Task or Task&amp;lt;TResult&amp;gt; that fully represents the original nested Task, including exceptions, cancellation state, etc.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;With Unwrap, we can fix the above scenario (note the bolded).&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;var userToken = LogOn(user, pass);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;var friends = userToken.ContinueWith(&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;_ =&amp;gt; GetFriendList(userToken.Result)).&lt;B style="mso-bidi-font-weight: normal"&gt;Unwrap();&lt;/B&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;var emails = friends.ContinueWith(_ =&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;var sentMails = new List&amp;lt;Task&amp;gt;();&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;foreach(var friend in friends.Result)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&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;sentMails.Add(SendEmail(friend, subject, body));&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;return Task.Factory.ContinueWhenAll(&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&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;sentMails.ToArray(), tasks =&amp;gt; Task.WaitAll(tasks));&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;}).&lt;B style="mso-bidi-font-weight: normal"&gt;Unwrap();&lt;/B&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;emails.ContinueWith(_ =&amp;gt; Console.WriteLine(“All emails sent”));&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;H1 style="MARGIN: 24pt 0in 0pt"&gt;&lt;FONT size=5&gt;&lt;FONT color=#376092&gt;&lt;FONT face=Cambria&gt;Parallel Namespace Change&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/H1&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;We’ve moved the Parallel class from the System.Threading namespace to the &lt;B style="mso-bidi-font-weight: normal"&gt;System.Threading.Tasks&lt;/B&gt; namespace.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We found that most applications needed to bring in both namespaces when using TPL, so why not put everything into one namespace?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Additionally, Parallel is such a common word (and will likely become more so in the future), and System.Threading such a common namespace, we wanted to reduce the chances of conflict with other .NET types as much as possible.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;Here’s a useful IDE tip.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Use “Ctrl + .” to automatically bring in the relevant namespace once you’ve typed a class/type name.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&amp;nbsp;&lt;IMG style="WIDTH: 335px; HEIGHT: 173px" title="Ctrl Period IDE" alt="Ctrl Period IDE" src="http://blogs.msdn.com/pfxteam/attachment/9917581.ashx" width=335 height=173 mce_src="http://blogs.msdn.com/pfxteam/attachment/9917581.ashx"&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;&lt;SPAN style="mso-no-proof: yes"&gt;&lt;?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /&gt;&lt;v:shapetype id=_x0000_t75 stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600"&gt;&lt;v:stroke joinstyle="miter"&gt;&lt;/v:stroke&gt;&lt;v:formulas&gt;&lt;v:f eqn="if lineDrawn pixelLineWidth 0"&gt;&lt;/v:f&gt;&lt;v:f eqn="sum @0 1 0"&gt;&lt;/v:f&gt;&lt;v:f eqn="sum 0 0 @1"&gt;&lt;/v:f&gt;&lt;v:f eqn="prod @2 1 2"&gt;&lt;/v:f&gt;&lt;v:f eqn="prod @3 21600 pixelWidth"&gt;&lt;/v:f&gt;&lt;v:f eqn="prod @3 21600 pixelHeight"&gt;&lt;/v:f&gt;&lt;v:f eqn="sum @0 0 1"&gt;&lt;/v:f&gt;&lt;v:f eqn="prod @6 1 2"&gt;&lt;/v:f&gt;&lt;v:f eqn="prod @7 21600 pixelWidth"&gt;&lt;/v:f&gt;&lt;v:f eqn="sum @8 21600 0"&gt;&lt;/v:f&gt;&lt;v:f eqn="prod @7 21600 pixelHeight"&gt;&lt;/v:f&gt;&lt;v:f eqn="sum @10 21600 0"&gt;&lt;/v:f&gt;&lt;/v:formulas&gt;&lt;v:path o:connecttype="rect" gradientshapeok="t" o:extrusionok="f"&gt;&lt;/v:path&gt;&lt;o:lock aspectratio="t" v:ext="edit"&gt;&lt;/o:lock&gt;&lt;/v:shapetype&gt;&lt;v:shape style="WIDTH: 251.25pt; HEIGHT: 129.75pt; VISIBILITY: visible; mso-wrap-style: square" id=Picture_x0020_4 alt="http://imladris.endoftheinternet.org:81/public/upload/ctrl+period.png" type="#_x0000_t75" o:spid="_x0000_i1025"&gt;&lt;v:imagedata o:title="ctrl+period" src="file:///C:\Users\dashih\AppData\Local\Temp\msohtmlclip1\01\clip_image001.png"&gt;&lt;/v:imagedata&gt;&lt;/v:shape&gt;&lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;H1 style="MARGIN: 24pt 0in 0pt"&gt;&lt;FONT size=5&gt;&lt;FONT color=#376092&gt;&lt;FONT face=Cambria&gt;Under the Covers&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/H1&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;Beta 2 contains quite a few bug fixes not done for Beta 1.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;All of them were important, but we’ll focus on only two here.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;First, Parallel.For and ForEach have been tweaked for better load-balancing with other workloads in the current or other AppDomains.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Essentially, the change was to service the parallel loops with Tasks that periodically retired and re-queued themselves, allowing other contenders to grab Threads and make progress.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;Second, waiting for Tasks in parent/child relationships has become more efficient.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In Beta 1 and before, parent Tasks waited for their children using explicit Waits, so even if a parent completed first, it would burn a thread until all of its children completed.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In Beta 2, parent Tasks wait for their children using callbacks; the parent maintains a count for number of children it has, and each child decrements the count as it completes.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This waiting logic significantly improves scalability.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;That’s it folks!&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We hope you’ve enjoyed this series.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;A href="http://www.microsoft.com/visualstudio/en-us/products/2010/default.mspx"&gt;&lt;FONT size=3 face=Calibri&gt;Download Beta 2&lt;/FONT&gt;&lt;/A&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt; and try it out!&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9917581" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/pfxteam/attachment/9917581.ashx" length="5851" type="image/x-png" /><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/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/Beta/default.aspx">Beta</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/.NET+4/default.aspx">.NET 4</category></item><item><title>Samples for Parallel Programming with the .NET Framework 4 Beta 2</title><link>http://blogs.msdn.com/pfxteam/archive/2009/11/02/9916318.aspx</link><pubDate>Mon, 02 Nov 2009 19:27:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9916318</guid><dc:creator>toub</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/pfxteam/comments/9916318.aspx</comments><wfw:commentRss>http://blogs.msdn.com/pfxteam/commentrss.aspx?PostID=9916318</wfw:commentRss><wfw:comment>http://blogs.msdn.com/pfxteam/rsscomments.aspx?PostID=9916318</wfw:comment><description>&lt;P&gt;We've posted a whole bunch of samples on Code Gallery showcasing&amp;nbsp;how to use the new parallelism support in the .NET Framework 4.&amp;nbsp; You can find them at &lt;A href="http://code.msdn.microsoft.com/ParExtSamples"&gt;http://code.msdn.microsoft.com/ParExtSamples&lt;/A&gt;.&amp;nbsp; Enjoy!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9916318" width="1" height="1"&gt;</description><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/Beta/default.aspx">Beta</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/.NET+4/default.aspx">.NET 4</category></item><item><title>What’s new in Beta 2 for the Task Parallel Library? (Part 2/3)</title><link>http://blogs.msdn.com/pfxteam/archive/2009/10/27/9913610.aspx</link><pubDate>Tue, 27 Oct 2009 18:02:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9913610</guid><dc:creator>dashih</dc:creator><slash:comments>10</slash:comments><comments>http://blogs.msdn.com/pfxteam/comments/9913610.aspx</comments><wfw:commentRss>http://blogs.msdn.com/pfxteam/commentrss.aspx?PostID=9913610</wfw:commentRss><wfw:comment>http://blogs.msdn.com/pfxteam/rsscomments.aspx?PostID=9913610</wfw:comment><description>&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT face=Calibri&gt;&lt;FONT size=3&gt;Related posts:&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT face=Calibri&gt;&lt;FONT size=3&gt;&lt;SPAN style="mso-ansi-language: EN" lang=EN&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;A href="http://blogs.msdn.com/pfxteam/archive/2009/10/19/9909371.aspx" mce_href="http://blogs.msdn.com/pfxteam/archive/2009/10/19/9909371.aspx"&gt;&lt;FONT size=3 face=Calibri&gt;What's new in Beta 2 for the Task Parallel Library (1/3)&lt;/FONT&gt;&lt;/A&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;A title="What's new in Beta 2 for the Task Parallel Library (3/3)" href="http://blogs.msdn.com/pfxteam/archive/2009/11/04/9917581.aspx" target=_blank mce_href="http://blogs.msdn.com/pfxteam/archive/2009/11/04/9917581.aspx"&gt;&lt;FONT size=3 face=Calibri&gt;What's new in Beta 2 for the Task Parallel Library (3/3)&lt;/FONT&gt;&lt;/A&gt;&lt;/DIV&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;Last week, we talked about how TPL adopted a new, better cancellation model.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Today, we’ll cover a change that makes &lt;B style="mso-bidi-font-weight: normal"&gt;Tasks Detached by Default&lt;/B&gt;, some &lt;B style="mso-bidi-font-weight: normal"&gt;ContinueWhenAll/Any Refactoring&lt;/B&gt;, and the handy &lt;B style="mso-bidi-font-weight: normal"&gt;UnobservedTaskException event&lt;/B&gt;.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;H2 style="MARGIN: 10pt 0in 0pt"&gt;&lt;FONT size=4&gt;&lt;FONT color=#4f81bd&gt;&lt;FONT face=Cambria&gt;Tasks are Detached by Default&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/H2&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;In Beta 2, we have changed an important default.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Tasks are now created as detached (instead of attached) if no options specify otherwise.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;Let’s consider the following code to review the difference between attached and detached Tasks.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;Task p = Task.Factory.StartNew(() =&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Task c = Task.Factory.StartNew(() =&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&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;DoWork();&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;});&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;});&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;p.Wait();&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;In Beta 1 and before, since the default options are used, ‘c’ is created as a child Task of Task ‘p’, the parent Task; we refer to this as Task ‘c’ being “attached” to Task ‘p’.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This means that the p.Wait() statement will not return until the call to DoWork completes, because parent Tasks do not complete until all of their child Tasks complete.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;To opt out of this behavior, a user needs to create ‘c’ with the DetachedFromParent option:&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Task c = Task.Factory.StartNew(() =&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&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;DoWork();&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}, &lt;B style="mso-bidi-font-weight: normal"&gt;TaskCreationOptions.DetachedFromParent&lt;/B&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;&lt;U&gt;The original code shown behaves differently in Beta 2&lt;/U&gt;.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Now, by default, ‘c’ is not related to ‘p’ (it’s “detached” by default), and the p.Wait() statement will return as soon as ‘p’ completes, regardless of the status of Task ‘c’ and thus regardless of when DoWork returns.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;To opt in to the parent/child relationship, a user needs to create ‘c’ with the AttachedToParent option:&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Task c = Task.Factory.StartNew(() =&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&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;DoWork();&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}, &lt;B style="mso-bidi-font-weight: normal"&gt;TaskCreationOptions.AttachedToParent&lt;/B&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT face=Calibri&gt;&lt;FONT size=3&gt;Here is a summary of the changes:&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT: -0.25in; MARGIN: 0in 0in 0pt 0.5in; mso-list: l1 level1 lfo1" class=MsoListParagraphCxSpFirst&gt;&lt;SPAN style="FONT-FAMILY: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;·&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Calibri&gt;&lt;FONT size=3&gt;Removed the DetachedFromParent option&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT: -0.25in; MARGIN: 0in 0in 0pt 0.5in; mso-list: l1 level1 lfo1" class=MsoListParagraphCxSpMiddle&gt;&lt;SPAN style="FONT-FAMILY: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;·&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Calibri&gt;&lt;FONT size=3&gt;Added the AttachedToParent option&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT: -0.25in; MARGIN: 0in 0in 10pt 0.5in; mso-list: l1 level1 lfo1" class=MsoListParagraphCxSpLast&gt;&lt;SPAN style="FONT-FAMILY: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;·&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Calibri&gt;&lt;FONT size=3&gt;Changed the default behavior so that Tasks do not enlist in parent/child relationships when no options are specified.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT face=Calibri&gt;&lt;FONT size=3&gt;There were a number of reasons why we decided that detached is the correct default and to move forward with this change, including:&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT: -0.25in; MARGIN: 0in 0in 0pt 0.5in; mso-list: l2 level1 lfo2" class=MsoListParagraphCxSpFirst&gt;&lt;SPAN style="FONT-FAMILY: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;·&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Calibri&gt;&lt;FONT size=3&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Many users were using attached Tasks unknowingly.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/B&gt;The vast majority of the time, users create Tasks for simple, asynchronous work.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In such scenarios, parent/child relationships (and the implicit waiting) are not needed.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We found through many interactions that folks were just going with the default options and were accidentally opting in to this behavior.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In the best case, this would only result in a slight performance cost. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;In the worst case, this would bring with it incorrect behavior that would lead to difficult to diagnose errors.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT: -0.25in; MARGIN: 0in 0in 0pt 0.5in; mso-list: l2 level1 lfo2" class=MsoListParagraphCxSpMiddle&gt;&lt;SPAN style="FONT-FAMILY: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;·&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Calibri&gt;&lt;FONT size=3&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Easier migration from ThreadPool.QueueUserWorkItem&lt;/B&gt;.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Tasks are now the recommended way to queue work to the ThreadPool, but the easiest way to create Tasks resulted in different behavior from QueueUserWorkItem (where there’s no concept of parent/child work items).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This change makes Task.Factory.StartNew (with no options) a true replacement for QueueUserWorkItem.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT: -0.25in; MARGIN: 0in 0in 10pt 0.5in; mso-list: l2 level1 lfo2" class=MsoListParagraphCxSpLast&gt;&lt;SPAN style="FONT-FAMILY: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;·&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Additional behavior should be opt-in and pay-for-play&lt;/B&gt;.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Almost everything in TPL that results in additional behavior is opt-in, e.g. cancellation, LongRunning, PreferFairness.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;With the Beta 1 default, users opt-out of parent/child relationships.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In Beta 2, users opt-in, making it consistent.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This makes the extra functionality provided by parent/child relationships pay-for-play, such that you don’t pay the cost for parents implicitly waiting for their children or for exceptions propagating from children to parents unless you need that functionality.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;H1 style="MARGIN: 24pt 0in 0pt"&gt;&lt;FONT size=5&gt;&lt;FONT color=#376092&gt;&lt;FONT face=Cambria&gt;ContinueWhenAny/All Refactoring&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/H1&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;We have refactored the set of ContinueWhenAny and ContinueWhenAll overloads to make things more intuitive, consistent, and complete.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;To demonstrate the main issue, let’s consider the following overload that was provided in Beta 1.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;public class TaskFactory&amp;lt;TResult&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;public Task&amp;lt;TNewResult&amp;gt; ContinueWhenAny(&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;Task&amp;lt;TResult&amp;gt;[] tasks, &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;Func&amp;lt;Task&amp;lt;TResult&amp;gt;, TNewResult&amp;gt; continuationFunction);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;This confused the meaning of TaskFactory&amp;lt;TResult&amp;gt;, which is meant to create tasks of type Task&amp;lt;TResult&amp;gt;.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;However, with these overloads, TaskFactory&amp;lt;TResult&amp;gt; could be used to create tasks of type Task&amp;lt;TNewResult&amp;gt;. As an example, consider the code:&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt 0.5in" class=MsoNormal&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;Task&amp;lt;int&amp;gt;[] taskOfInts = ...;&lt;BR&gt;Task&amp;lt;&lt;B style="mso-bidi-font-weight: normal"&gt;string&lt;/B&gt;&amp;gt; t = Task&amp;lt;&lt;B style="mso-bidi-font-weight: normal"&gt;int&lt;/B&gt;&amp;gt;.Factory.ContinueWhenAll(taskOfInts, _ =&amp;gt; “”);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;This compiles and works just fine, but the type parameter mismatch (shown in bold) is certainly odd.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;To address this, we changed a bunch of overloads, so that instead of taking Task&amp;lt;TResult&amp;gt;s and returning a Task&amp;lt;TNewResult&amp;gt;, they take Task&amp;lt;TAntecedentResult&amp;gt;s and return Task&amp;lt;TResult&amp;gt;s.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For example, the overload that replaced the above is:&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=Code&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;public Task&amp;lt;TResult&amp;gt; ContinueWhenAny&amp;lt;TAntecedentResult&amp;gt;(&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=Code&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Task&amp;lt;TAntecedentResult&amp;gt;[] tasks,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=Code&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Func&amp;lt;Task&amp;lt;TAntecedentResult&amp;gt;, TResult&amp;gt; continuationFunction);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=Code&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;And the above example becomes:&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt 0.5in" class=MsoNormal&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;Task&amp;lt;int&amp;gt;[] taskOfInts = ...;&lt;BR&gt;Task&amp;lt;string&amp;gt; t = Task&amp;lt;string&amp;gt;.Factory.ContinueWhenAll(taskOfInts, _ =&amp;gt; “”);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT face=Calibri&gt;&lt;FONT size=3&gt;In addition to this change, we also added, removed, or modified a number of other overloads to make the set consistent and complete.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Now, the entire set of ContinueWhenAll and ContinueWhenAny overloads follow these clear rules:&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT: -0.25in; MARGIN: 0in 0in 0pt 0.5in; mso-list: l0 level1 lfo3" class=MsoListParagraphCxSpFirst&gt;&lt;SPAN style="FONT-FAMILY: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;·&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Calibri&gt;&lt;FONT size=3&gt;A TaskFactory creates Tasks, but also provides overloads to create Task&amp;lt;TResult&amp;gt;s.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT: -0.25in; MARGIN: 0in 0in 10pt 0.5in; mso-list: l0 level1 lfo3" class=MsoListParagraphCxSpLast&gt;&lt;SPAN style="FONT-FAMILY: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;·&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;A TaskFactory&amp;lt;TResult&amp;gt; only ever creates Task&amp;lt;TResult&amp;gt;s (never Tasks or Task&amp;lt;TNewResult&amp;gt;s).&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;H1 style="MARGIN: 24pt 0in 0pt"&gt;&lt;FONT size=5&gt;&lt;FONT color=#376092&gt;&lt;FONT face=Cambria&gt;UnobservedTaskException event&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/H1&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;We’ve added an event that fires for every Task exception that goes unobserved.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Recall that to “observe” a Task’s exceptions, you must either Wait on the Task or access its Exception property after it has completed.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;At least one of these actions must be done before the Task object is garbage collected, or its exceptions will propagate (currently this occurs on the finalizer thread).&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;The new static event resides on the TaskScheduler class, and subscribing to it is straightforward.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Here’s an example to log all unobserved exceptions and mark them as observed (preventing them from being propagated).&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;TaskScheduler.UnobservedTaskException += &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;(object sender, UnobservedTaskExceptionEventArgs exceptionArgs) =&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&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;exceptionArgs.SetObserved();&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&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;LogException(exceptionArgs.Exception);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;};&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 0pt 0.5in" class=MsoNoSpacing&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;Some customers have complained that TPL’s exception policy is too strict.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The UnobservedTaskException event provides an easy way out by allowing you to simply squash all Task exceptions in an application (though using it in this manner is not recommended).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The primary reason that we made the addition was to support host-plugin scenarios where a host application can still be perfectly useful in the presence of some truly harmless exceptions (thrown by buggy plugins).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;These scenarios may be achieved using the UnobservedTaskException event in conjunction with AppDomains to sandbox plugins.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Look for a future post that describes this in more detail!&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;We’re done for now!&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The 3&lt;SUP&gt;rd&lt;/SUP&gt; and final post of this series will cover the new Unwrap APIs, a Parallel namespace change, and some changes under the covers.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9913610" 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/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><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Beta/default.aspx">Beta</category></item><item><title>What’s new in Beta 2 for the Task Parallel Library? (Part 1/3)</title><link>http://blogs.msdn.com/pfxteam/archive/2009/10/19/9909371.aspx</link><pubDate>Mon, 19 Oct 2009 19:42:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9909371</guid><dc:creator>dashih</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/pfxteam/comments/9909371.aspx</comments><wfw:commentRss>http://blogs.msdn.com/pfxteam/commentrss.aspx?PostID=9909371</wfw:commentRss><wfw:comment>http://blogs.msdn.com/pfxteam/rsscomments.aspx?PostID=9909371</wfw:comment><description>&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;Related&amp;nbsp;posts:&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3 face=Calibri&gt;&lt;A title="What's new in Beta 2 for the Task Parallel Library? (Part 2/3)" href="http://blogs.msdn.com/pfxteam/archive/2009/10/27/9913610.aspx" mce_href="http://blogs.msdn.com/pfxteam/archive/2009/10/27/9913610.aspx"&gt;What's new in Beta 2 for the Task Parallel Library? (Part 2/3)&lt;/A&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;
&lt;DIV style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3 face=Calibri&gt;&lt;A title="What's new in Beta 2 for the Task Parallel Library? (Part 3/3)" href="http://blogs.msdn.com/pfxteam/archive/2009/11/04/9917581.aspx" target=_blank mce_href="http://blogs.msdn.com/pfxteam/archive/2009/11/04/9917581.aspx"&gt;What's new in Beta 2 for the Task Parallel Library? (Part 3/3)&lt;/A&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/DIV&gt;&lt;/DIV&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;Visual Studio 2010 and .NET 4 Beta 2 is&amp;nbsp;here!&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In terms of completeness and readiness for production coding, Beta 2 promises to be much better than Beta 1, and TPL is one component that delivers significant improvements over what was previously available.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;To get you excited about it, this series of posts details key additions and changes for Beta 2.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Enjoy!&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3 face=Calibri&gt;In this post, we’re talking about &lt;B style="mso-bidi-font-weight: normal"&gt;cancellation&lt;/B&gt;.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;A few months ago, our flurry of “What’s new in Beta 1” posts hinted at a new cancellation model and promised more information about it.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We made good on that promise with &lt;/FONT&gt;&lt;A href="http://blogs.msdn.com/pfxteam/archive/2009/05/22/9635790.aspx" mce_href="http://blogs.msdn.com/pfxteam/archive/2009/05/22/9635790.aspx"&gt;&lt;FONT color=#0000ff size=3 face=Calibri&gt;.NET 4 Cancellation Framework&lt;/FONT&gt;&lt;/A&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;, and this post goes further to explain how TPL, specifically, has fully adopted the new model.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;H2 style="MARGIN: 10pt 0in 0pt"&gt;&lt;FONT size=4&gt;&lt;FONT color=#4f81bd&gt;&lt;FONT face=Cambria&gt;The Old Way (Beta 1 and before)&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/H2&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;Let’s consider the following code to review the old TPL cancellation model.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;Task myTask = Task.Factory.StartNew(() =&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;for (; ; )&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&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;if (Task.Current.IsCancellationRequested)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&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;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&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;Task.Current.AcknowledgeCancellation();&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&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;return;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&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;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&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;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;});&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;// Elsewhere.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;myTask.Cancel();&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;myTask just loops infinitely, checking its IsCancellationRequested property to see if it has been canceled.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Elsewhere, cancellation is requested on myTask using the Cancel method.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;At that point, myTask agrees to get canceled by calling its AcknowledgeCancellation method and returning.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is all necessary, because Task cancellation is cooperative; &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;to enter the Canceled state, outside logic must request cancellation &lt;U&gt;and&lt;/U&gt; the Task must acknowledge that cancellation request.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;However, note that cooperative cancellation is only relevant for already running Tasks.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If a Task’s Cancel method is called before it is in the Running state, it will transition directly into the Canceled state.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;Waiting on a canceled Task results in a TaskCanceledException wrapped in an AggregateException, hence the try/catch block.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Executing this code prints “Canceled” to the console, indicating that myTask was successfully canceled.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;This approach works, but we identified a number of problems with it including the following:&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT: -0.25in; MARGIN: 0in 0in 0pt 0.5in; mso-list: l0 level1 lfo1" class=MsoListParagraphCxSpFirst&gt;&lt;SPAN style="mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3 face=Calibri&gt;1.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;The cancellation model required exposing a Task.Current static property.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This leaks implementation details from libraries that utilize Tasks internally; any code called from the Task can muck with the current Task or take dependencies on its existence.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Imagine calling into 3&lt;SUP&gt;rd&lt;/SUP&gt; party code and having that code cancel your Tasks, schedule continuations off of them, etc.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT: -0.25in; MARGIN: 0in 0in 0pt 0.5in; mso-list: l0 level1 lfo1" class=MsoListParagraphCxSpMiddle&gt;&lt;SPAN style="mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3 face=Calibri&gt;2.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;Anyone with a Task’s reference can request cancellation on it.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In many scenarios, it is valuable to separate the ability to check for cancellation and the ability to actually request cancellation.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT: -0.25in; MARGIN: 0in 0in 0pt 0.5in; mso-list: l0 level1 lfo1" class=MsoListParagraphCxSpMiddle&gt;&lt;SPAN style="mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3 face=Calibri&gt;3.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;From a cancellation perspective, Tasks didn’t compose well with other APIs that were cancelable, such as executing a cancelable PLINQ query inside of a Task.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT: -0.25in; MARGIN: 0in 0in 10pt 0.5in; mso-list: l0 level1 lfo1" class=MsoListParagraphCxSpLast&gt;&lt;SPAN style="mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3 face=Calibri&gt;4.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;Tasks were often more expensive than they needed to be, due to needing to track extra cancellation state per Task.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;H2 style="MARGIN: 10pt 0in 0pt"&gt;&lt;FONT size=4&gt;&lt;FONT color=#4f81bd&gt;&lt;FONT face=Cambria&gt;The New Way (Beta 2 and beyond)&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/H2&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;The new TPL cancellation model is centered around two types: CancellationTokenSource and CancellationToken.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;You can read up about them in the post linked to above, but here is a simplified overview of their APIs:&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt 0.5in" class=MsoNormal&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: Consolas; FONT-SIZE: 9pt; mso-bidi-font-family: 'Times New Roman'; mso-bidi-theme-font: minor-bidi"&gt;namespace System.Threading&lt;BR&gt;{&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;public sealed class CancellationTokenSource&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;BR&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;public void Cancel();&lt;BR&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;public CancellationToken Token { get; }&lt;BR&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 style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;public struct CancellationToken&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;BR&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;public Boolean IsCancellationRequested { get; }&lt;BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;public void ThrowIfCancellationRequested();&lt;BR&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 style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;BR&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT face=Calibri&gt;&lt;FONT size=3&gt;Here’s the gist.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;A CancellationTokenSource contains a CancellationToken, and it can request cancellation on that token using a Cancel method.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;A CancellationToken can only check if cancellation has been requested on it.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Ignore the ThrowIfCancellationRequested method for now; we’ll see why it’s handy later.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT face=Calibri&gt;&lt;FONT size=3&gt;Adopting the new model involved not only adding support for these two types, but also ripping out the old model.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Here’s a summary of the changes:&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT: -0.25in; MARGIN: 0in 0in 0pt 0.5in; mso-list: l1 level1 lfo2" class=MsoListParagraphCxSpFirst&gt;&lt;SPAN style="FONT-FAMILY: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;·&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Calibri&gt;&lt;FONT size=3&gt;All cancellation-related APIs on the Task class were removed (Cancel, AcknowledgeCancellation, IsCancellationRequested, etc)&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT: -0.25in; MARGIN: 0in 0in 0pt 0.5in; mso-list: l1 level1 lfo2" class=MsoListParagraphCxSpMiddle&gt;&lt;SPAN style="FONT-FAMILY: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;·&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Calibri&gt;&lt;FONT size=3&gt;Other APIs that were no longer relevant were removed (Task.Current, Task.Parent, TaskCreationOptions.RespectParentCancellation, etc)&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT: -0.25in; MARGIN: 0in 0in 10pt 0.5in; mso-list: l1 level1 lfo2" class=MsoListParagraphCxSpLast&gt;&lt;SPAN style="FONT-FAMILY: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;·&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;Overloads that accept CancellationToken were added to many methods (StartNew, ContinueWith, etc)&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;And now, here’s a table that outlines how achieving cancellation in TPL has changed:&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;TABLE style="BORDER-BOTTOM: medium none; BORDER-LEFT: medium none; BORDER-COLLAPSE: collapse; BORDER-TOP: medium none; BORDER-RIGHT: medium none; mso-border-top-alt: solid black 1.0pt; mso-border-top-themecolor: text1; mso-border-bottom-alt: solid black 1.0pt; mso-border-bottom-themecolor: text1; mso-yfti-tbllook: 1184; mso-padding-alt: 0in 5.4pt 0in 5.4pt" class=LightShading1 border=1 cellSpacing=0 cellPadding=0 class="LightShading1"&gt;
&lt;TBODY&gt;
&lt;TR style="mso-yfti-irow: -1; mso-yfti-firstrow: yes"&gt;
&lt;TD style="BORDER-BOTTOM: black 1pt solid; BORDER-LEFT: #f0f0f0; PADDING-BOTTOM: 0in; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 159.6pt; PADDING-RIGHT: 5.4pt; BORDER-TOP: black 1pt solid; BORDER-RIGHT: #f0f0f0; PADDING-TOP: 0in; mso-border-top-themecolor: text1; mso-border-bottom-themecolor: text1" vAlign=top width=213&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt; mso-yfti-cnfc: 5" class=MsoNormal&gt;&lt;B&gt;&lt;SPAN style="COLOR: black; FONT-SIZE: 9pt; mso-themecolor: text1; mso-themeshade: 191"&gt;&lt;FONT face=Calibri&gt;Action&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD style="BORDER-BOTTOM: black 1pt solid; BORDER-LEFT: #f0f0f0; PADDING-BOTTOM: 0in; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 159.6pt; PADDING-RIGHT: 5.4pt; BORDER-TOP: black 1pt solid; BORDER-RIGHT: #f0f0f0; PADDING-TOP: 0in; mso-border-top-themecolor: text1; mso-border-bottom-themecolor: text1" vAlign=top width=213&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt; mso-yfti-cnfc: 1" class=MsoNormal&gt;&lt;B&gt;&lt;SPAN style="COLOR: black; FONT-SIZE: 9pt; mso-themecolor: text1; mso-themeshade: 191"&gt;&lt;FONT face=Calibri&gt;Old Model&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD style="BORDER-BOTTOM: black 1pt solid; BORDER-LEFT: #f0f0f0; PADDING-BOTTOM: 0in; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 159.6pt; PADDING-RIGHT: 5.4pt; BORDER-TOP: black 1pt solid; BORDER-RIGHT: #f0f0f0; PADDING-TOP: 0in; mso-border-top-themecolor: text1; mso-border-bottom-themecolor: text1" vAlign=top width=213&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt; mso-yfti-cnfc: 1" class=MsoNormal&gt;&lt;B&gt;&lt;SPAN style="COLOR: black; FONT-SIZE: 9pt; mso-themecolor: text1; mso-themeshade: 191"&gt;&lt;FONT face=Calibri&gt;New Model&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR style="mso-yfti-irow: 0"&gt;
&lt;TD style="BORDER-BOTTOM: #f0f0f0; BORDER-LEFT: #f0f0f0; PADDING-BOTTOM: 0in; PADDING-LEFT: 5.4pt; WIDTH: 159.6pt; PADDING-RIGHT: 5.4pt; BACKGROUND: #bfbfbf; BORDER-TOP: #f0f0f0; BORDER-RIGHT: #f0f0f0; PADDING-TOP: 0in; mso-background-themecolor: text1; mso-background-themetint: 63" vAlign=top width=213&gt;&lt;FONT face=Calibri&gt;&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD style="BORDER-BOTTOM: #f0f0f0; BORDER-LEFT: #f0f0f0; PADDING-BOTTOM: 0in; PADDING-LEFT: 5.4pt; WIDTH: 159.6pt; PADDING-RIGHT: 5.4pt; BACKGROUND: #bfbfbf; BORDER-TOP: #f0f0f0; BORDER-RIGHT: #f0f0f0; PADDING-TOP: 0in; mso-background-themecolor: text1; mso-background-themetint: 63" vAlign=top width=213&gt;&lt;FONT face=Calibri&gt;&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD style="BORDER-BOTTOM: #f0f0f0; BORDER-LEFT: #f0f0f0; PADDING-BOTTOM: 0in; PADDING-LEFT: 5.4pt; WIDTH: 159.6pt; PADDING-RIGHT: 5.4pt; BACKGROUND: #bfbfbf; BORDER-TOP: #f0f0f0; BORDER-RIGHT: #f0f0f0; PADDING-TOP: 0in; mso-background-themecolor: text1; mso-background-themetint: 63" vAlign=top width=213&gt;&lt;FONT face=Calibri&gt;&lt;/FONT&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR style="mso-yfti-irow: 1"&gt;
&lt;TD style="BORDER-BOTTOM: #f0f0f0; BORDER-LEFT: #f0f0f0; PADDING-BOTTOM: 0in; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 159.6pt; PADDING-RIGHT: 5.4pt; BORDER-TOP: #f0f0f0; BORDER-RIGHT: #f0f0f0; PADDING-TOP: 0in" vAlign=top width=213&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt; mso-yfti-cnfc: 4" class=MsoNormal&gt;&lt;SPAN style="COLOR: black; FONT-SIZE: 9pt; mso-bidi-font-weight: bold; mso-themecolor: text1; mso-themeshade: 191"&gt;&lt;FONT face=Calibri&gt;To set up cancellation&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD style="BORDER-BOTTOM: #f0f0f0; BORDER-LEFT: #f0f0f0; PADDING-BOTTOM: 0in; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 159.6pt; PADDING-RIGHT: 5.4pt; BORDER-TOP: #f0f0f0; BORDER-RIGHT: #f0f0f0; PADDING-TOP: 0in" vAlign=top width=213&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt" class=MsoNormal&gt;&lt;SPAN style="COLOR: black; FONT-SIZE: 9pt; mso-themecolor: text1; mso-themeshade: 191"&gt;&lt;FONT face=Calibri&gt;Just create a Task&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD style="BORDER-BOTTOM: #f0f0f0; BORDER-LEFT: #f0f0f0; PADDING-BOTTOM: 0in; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 159.6pt; PADDING-RIGHT: 5.4pt; BORDER-TOP: #f0f0f0; BORDER-RIGHT: #f0f0f0; PADDING-TOP: 0in" vAlign=top width=213&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt" class=MsoNormal&gt;&lt;SPAN style="COLOR: black; FONT-SIZE: 9pt; mso-themecolor: text1; mso-themeshade: 191"&gt;&lt;FONT face=Calibri&gt;Create a CancellationTokenSource and pass its Token to an API that creates a Task.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR style="mso-yfti-irow: 2"&gt;
&lt;TD style="BORDER-BOTTOM: #f0f0f0; BORDER-LEFT: #f0f0f0; PADDING-BOTTOM: 0in; PADDING-LEFT: 5.4pt; WIDTH: 159.6pt; PADDING-RIGHT: 5.4pt; BACKGROUND: #bfbfbf; BORDER-TOP: #f0f0f0; BORDER-RIGHT: #f0f0f0; PADDING-TOP: 0in; mso-background-themecolor: text1; mso-background-themetint: 63" vAlign=top width=213&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt; mso-yfti-cnfc: 68" class=MsoNormal&gt;&lt;SPAN style="COLOR: black; FONT-SIZE: 9pt; mso-bidi-font-weight: bold; mso-themecolor: text1; mso-themeshade: 191"&gt;&lt;FONT face=Calibri&gt;To check if cancellation has been requested&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD style="BORDER-BOTTOM: #f0f0f0; BORDER-LEFT: #f0f0f0; PADDING-BOTTOM: 0in; PADDING-LEFT: 5.4pt; WIDTH: 159.6pt; PADDING-RIGHT: 5.4pt; BACKGROUND: #bfbfbf; BORDER-TOP: #f0f0f0; BORDER-RIGHT: #f0f0f0; PADDING-TOP: 0in; mso-background-themecolor: text1; mso-background-themetint: 63" vAlign=top width=213&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt; mso-yfti-cnfc: 64" class=MsoNormal&gt;&lt;SPAN style="COLOR: black; FONT-SIZE: 9pt; mso-themecolor: text1; mso-themeshade: 191"&gt;&lt;FONT face=Calibri&gt;Check the IsCancellationRequested property on the relevant Task&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD style="BORDER-BOTTOM: #f0f0f0; BORDER-LEFT: #f0f0f0; PADDING-BOTTOM: 0in; PADDING-LEFT: 5.4pt; WIDTH: 159.6pt; PADDING-RIGHT: 5.4pt; BACKGROUND: #bfbfbf; BORDER-TOP: #f0f0f0; BORDER-RIGHT: #f0f0f0; PADDING-TOP: 0in; mso-background-themecolor: text1; mso-background-themetint: 63" vAlign=top width=213&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt; mso-yfti-cnfc: 64" class=MsoNormal&gt;&lt;SPAN style="COLOR: black; FONT-SIZE: 9pt; mso-themecolor: text1; mso-themeshade: 191"&gt;&lt;FONT face=Calibri&gt;Check the IsCancellationRequested property on the CancellationToken that was passed to the API that created the Task&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR style="mso-yfti-irow: 3"&gt;
&lt;TD style="BORDER-BOTTOM: #f0f0f0; BORDER-LEFT: #f0f0f0; PADDING-BOTTOM: 0in; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 159.6pt; PADDING-RIGHT: 5.4pt; BORDER-TOP: #f0f0f0; BORDER-RIGHT: #f0f0f0; PADDING-TOP: 0in" vAlign=top width=213&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt; mso-yfti-cnfc: 4" class=MsoNormal&gt;&lt;SPAN style="COLOR: black; FONT-SIZE: 9pt; mso-bidi-font-weight: bold; mso-themecolor: text1; mso-themeshade: 191"&gt;&lt;FONT face=Calibri&gt;To acknowledge cancellation&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD style="BORDER-BOTTOM: #f0f0f0; BORDER-LEFT: #f0f0f0; PADDING-BOTTOM: 0in; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 159.6pt; PADDING-RIGHT: 5.4pt; BORDER-TOP: #f0f0f0; BORDER-RIGHT: #f0f0f0; PADDING-TOP: 0in" vAlign=top width=213&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt" class=MsoNormal&gt;&lt;SPAN style="COLOR: black; FONT-SIZE: 9pt; mso-themecolor: text1; mso-themeshade: 191"&gt;&lt;FONT face=Calibri&gt;Check to ensure that IsCancellationRequested is true, then call the AcknowledgeCancellation() method on the relevant Task&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD style="BORDER-BOTTOM: #f0f0f0; BORDER-LEFT: #f0f0f0; PADDING-BOTTOM: 0in; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 159.6pt; PADDING-RIGHT: 5.4pt; BORDER-TOP: #f0f0f0; BORDER-RIGHT: #f0f0f0; PADDING-TOP: 0in" vAlign=top width=213&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt" class=MsoNormal&gt;&lt;SPAN style="COLOR: black; FONT-SIZE: 9pt; mso-themecolor: text1; mso-themeshade: 191"&gt;&lt;FONT face=Calibri&gt;Throw an OperationCanceledException with the task’s CancellationToken&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR style="mso-yfti-irow: 4; mso-yfti-lastrow: yes"&gt;
&lt;TD style="BORDER-BOTTOM: black 1pt solid; BORDER-LEFT: #f0f0f0; PADDING-BOTTOM: 0in; PADDING-LEFT: 5.4pt; WIDTH: 159.6pt; PADDING-RIGHT: 5.4pt; BACKGROUND: #bfbfbf; BORDER-TOP: #f0f0f0; BORDER-RIGHT: #f0f0f0; PADDING-TOP: 0in; mso-border-bottom-themecolor: text1; mso-background-themecolor: text1; mso-background-themetint: 63" vAlign=top width=213&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt; mso-yfti-cnfc: 68" class=MsoNormal&gt;&lt;SPAN style="COLOR: black; FONT-SIZE: 9pt; mso-bidi-font-weight: bold; mso-themecolor: text1; mso-themeshade: 191"&gt;&lt;FONT face=Calibri&gt;To cancel a tree of tasks&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD style="BORDER-BOTTOM: black 1pt solid; BORDER-LEFT: #f0f0f0; PADDING-BOTTOM: 0in; PADDING-LEFT: 5.4pt; WIDTH: 159.6pt; PADDING-RIGHT: 5.4pt; BACKGROUND: #bfbfbf; BORDER-TOP: #f0f0f0; BORDER-RIGHT: #f0f0f0; PADDING-TOP: 0in; mso-border-bottom-themecolor: text1; mso-background-themecolor: text1; mso-background-themetint: 63" vAlign=top width=213&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt; mso-yfti-cnfc: 64" class=MsoNormal&gt;&lt;SPAN style="COLOR: black; FONT-SIZE: 9pt; mso-themecolor: text1; mso-themeshade: 191"&gt;&lt;FONT face=Calibri&gt;Create all of the tasks as attached tasks and with the RespectParentCancellation flag set, then cancel the root task.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD style="BORDER-BOTTOM: black 1pt solid; BORDER-LEFT: #f0f0f0; PADDING-BOTTOM: 0in; PADDING-LEFT: 5.4pt; WIDTH: 159.6pt; PADDING-RIGHT: 5.4pt; BACKGROUND: #bfbfbf; BORDER-TOP: #f0f0f0; BORDER-RIGHT: #f0f0f0; PADDING-TOP: 0in; mso-border-bottom-themecolor: text1; mso-background-themecolor: text1; mso-background-themetint: 63" vAlign=top width=213&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt; mso-yfti-cnfc: 64" class=MsoNormal&gt;&lt;SPAN style="COLOR: black; FONT-SIZE: 9pt; mso-themecolor: text1; mso-themeshade: 191"&gt;&lt;FONT face=Calibri&gt;Pass the same CancellationToken to all Tasks, then cancel the associated CancellationTokenSource&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;o:p&gt;&lt;FONT size=3 face=Calibri&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;To see how this all works, let’s rewrite the code above for Beta 2.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;CancellationTokenSource cts = new CancellationTokenSource();&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;CancellationToken token = cts.Token;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;Task myTask = Task.Factory.StartNew(() =&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;for (; ; )&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&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;token.ThrowIfCancellationRequested();&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&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;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;}, token);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;// Elsewhere.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;cts.Cancel();&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN: 0in 0in 0pt 0.5in; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;A CancellationTokenSource (cts) is initialized, and a CancellationToken (token) is initialized to cts’s Token.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;myTask still loops indefinitely, but now it calls ThrowIfCancellationRequested.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This method just checks the IsCancellationRequested property on a CancellationToken.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If true, it throws&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;an OperationCanceledException(token), which is the way to acknowledge cancellation in the new model.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Elsewhere, Cancel is called on cts to request cancellation on myTask.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;The new model addresses all of the problems with the old model listed above:&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT: -0.25in; MARGIN: 0in 0in 0pt 0.5in; mso-list: l2 level1 lfo3" class=MsoListParagraphCxSpFirst&gt;&lt;SPAN style="mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3 face=Calibri&gt;1.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;No more Task.Current (Task.Parent was removed too, as it could be used to get at the current Task).&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT: -0.25in; MARGIN: 0in 0in 0pt 0.5in; mso-list: l2 level1 lfo3" class=MsoListParagraphCxSpMiddle&gt;&lt;SPAN style="mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3 face=Calibri&gt;2.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;The ability to check for cancellation requests may now be separated from the ability to request cancellation.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If only the former is desired, grant access to the CancellationToken only.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="TEXT-INDENT: -0.25in; MARGIN: 0in 0in 10pt 0.5in; mso-list: l2 level1 lfo3" class=MsoListParagraphCxSpLast&gt;&lt;SPAN style="mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3 face=Calibri&gt;3.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;TPL now uses the new .NET 4 cancellation types.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;You can use the same CancellationToken{Source} to effect cancellation on multiple Tasks, Parallel.For calls, PLINQ queries, and more, all at once.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This provides both better composition and better performance.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;Finally, there are other advantages to this model.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;One is that it is much easier to organize cancellation sets within a large nest of Tasks; just create the right number of tokens and pass them around accordingly.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Before, this scenario would have required tedious bookkeeping of many Task references and/or careful architecting of cancellation chains using TaskCreationOptions.RespectParentCancellation.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;That’s it for now.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The next post in the series will discuss a change regarding Tasks and parent/child relationships.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9909371" 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/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><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Beta/default.aspx">Beta</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Cancellation/default.aspx">Cancellation</category></item><item><title>Does Parallel.For use one Task per iteration?</title><link>http://blogs.msdn.com/pfxteam/archive/2009/05/26/9641563.aspx</link><pubDate>Tue, 26 May 2009 18:31:35 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9641563</guid><dc:creator>toub</dc:creator><slash:comments>6</slash:comments><comments>http://blogs.msdn.com/pfxteam/comments/9641563.aspx</comments><wfw:commentRss>http://blogs.msdn.com/pfxteam/commentrss.aspx?PostID=9641563</wfw:commentRss><wfw:comment>http://blogs.msdn.com/pfxteam/rsscomments.aspx?PostID=9641563</wfw:comment><description>&lt;p&gt;In .NET 4, the new Parallel class provides For, ForEach, and Invoke methods for performing operations in parallel. One mental model that some folks use when thinking about Parallel.For is that it’s equivalent to running one System.Threading.Tasks.Task per iteration, e.g. that a loop like:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Parallel.For(0, N, i =&amp;gt;     &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; DoWork(i);      &lt;br /&gt;});&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;is equivalent to:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;var tasks = new List&amp;lt;Task&amp;gt;(N);     &lt;br /&gt;for(int i=0; i&amp;lt;N; i++)      &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; tasks.Add(Task.Factory.StartNew(state =&amp;gt; DoWork((int)state), i));      &lt;br /&gt;}      &lt;br /&gt;Task.WaitAll(tasks.ToArray());&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;From the perspective of every iteration potentially running in parallel with every other iteration, this is an ok mental model.&amp;#160; However, it can also lead to some misunderstandings as to Parallel’s behavior.&amp;#160; Parallel, in fact, does not necessarily use one Task per iteration, as that could add significantly more overhead than is necessary.&lt;/p&gt;  &lt;p&gt;Under the covers, Parallel.For tries to use the minimum number of tasks necessary to complete the loop as fast as possible.&amp;#160; A better mental model includes Parallel spinning up tasks as threads are available to process those tasks, and each of those tasks then participating in a range management scheme.&amp;#160; A task asks for a chunk to be done (which may include multiple iterations), processes that work, and then goes back for more.&amp;#160; The chunk sizes may vary based on a variety of factors, including the number of tasks participating, the load on the machine, the size of the iteration space, and so forth.&lt;/p&gt;  &lt;p&gt;One of the most important takeaways from this revised mental model is that iterations are handed out in indivisible chunks, and only one thread is involved in the processing of a particular chunk.&amp;#160; This has implications for interdependencies between iterations.&amp;#160; If iteration &lt;em&gt;i&lt;/em&gt; blocks waiting for iteration &lt;em&gt;i+1&lt;/em&gt; to be completed, and iterations &lt;em&gt;i&lt;/em&gt; and &lt;em&gt;i+1&lt;/em&gt; are both allocated to the same chunk, the loop will likely deadlock.&amp;#160; The thread processing those iterations will block processing iteration &lt;em&gt;i&lt;/em&gt;, but as that thread is also responsible for processing iteration &lt;em&gt;i+1&lt;/em&gt;, iteration &lt;em&gt;i+1&lt;/em&gt; will never get processed and iteration &lt;em&gt;i&lt;/em&gt; will never unblock.&lt;/p&gt;  &lt;p&gt;As such, if you find yourself in an obscure situation like this, you have several options.&amp;#160; You can fall back to using a Task per iteration, as per the original model shown previously.&amp;#160; You can also take advantage of custom partitioning support, which we’ll discuss more in a future post. Of course, Parallel provides significantly more functionality than is shown in that previous Tasks-based code snippet.&amp;#160; Parallel tracks unhandled exceptions and prevents additional iterations from starting in the event of an exception.&amp;#160; It supports cancellation, setting a maximum degree of parallelism, targeting a particular scheduler, breaking out of a loop early with ParallelLoopState.Stop/Break, and so forth.&amp;#160; All of this functionality could be layered on top of Tasks with extra code and effort; after all, that’s how Parallel works (at least in the current bits; the implementation may of course change in the future).&lt;/p&gt;  &lt;p&gt;Parallel.ForEach has similar implications as Parallel.For.&amp;#160; A decent mental model for Parallel.ForEach when the source is indexible (like an array or a list) involves simply delegating to Parallel.For.&amp;#160; For example, the following Parallel.ForEach loop:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;T [] source = …;     &lt;br /&gt;Parallel.ForEach(source, item =&amp;gt;      &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; DoWork(item);      &lt;br /&gt;});&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;could be thought of as being implemented like this:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;T [] source = …;     &lt;br /&gt;Parallel.For(0, source.Length, i=&amp;gt;      &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; var item = source[i];      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; DoWork(item);      &lt;br /&gt;});&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Since our model for Parallel.For involves chunking, so too does our model for Parallel.ForEach.&amp;#160; This is also true when Parallel.ForEach works with a non-indexable IEnumerable&amp;lt;T&amp;gt; as the data source.&amp;#160; IEnumerable&amp;lt;T&amp;gt; isn’t thread-safe (even if the data source being enumerated is in some fashion), in that it requires two calls to retrieve the next item: one to MoveNext() to advance the enumerator, and one to Current to retrieve the item.&amp;#160; Thus, when working with an enumerator, the threads involved in a Parallel.ForEach (as is also true with PLINQ) need to use a lock while accessing an enumerable data source.&amp;#160; Taking that lock for each item in the data source proves typically to be prohibitively expensive, and thus Parallel.ForEach ammortizes the cost of the lock across multiple items by chunking the input source: acquire the lock, enumerate some number of elements from the data source into a private data structure, release the lock, and then process that privatized chunk (we’ll discuss this in more detail in a future post).&amp;#160; As a result, this suffers from the same cross-iteration dependency issue as previously described.&amp;#160; If the processing of element &lt;em&gt;i&lt;/em&gt; in the enumerable blocks waiting for element &lt;em&gt;i+1&lt;/em&gt; to be processed, the processing may deadlock if those two elements happen to be in the same privatized chunk.&amp;#160; As with Parallel.For, you can always fall back to using Tasks directly if you have these kind of unusual dependencies.&lt;/p&gt;  &lt;p&gt;Parallel.Invoke is a more interesting creature.&amp;#160; The signature of the primary Invoke overload is:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;public static void Invoke(params Action[] actions);&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This signature lends itself well to two different mental models.&amp;#160; The first, as with Parallel.For/ForEach, is simply to use a Task to run each action:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;var tasks = new List&amp;lt;Task&amp;gt;(actions.Length);     &lt;br /&gt;foreach(var action in actions)      &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; tasks.Add(Task.Factory.StartNew(action));      &lt;br /&gt;}      &lt;br /&gt;Task.WaitAll(tasks.ToArray());&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Another is based on observing that we’re really dealing with an array as an input data source, and we can use Parallel.ForEach:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Parallel.ForEach(actions, action =&amp;gt; action());&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;In fact, the current (Beta 1) implementation of Parallel.Invoke uses approaches similar to both of these models, and it chooses which to use based on a variety of circumstances.&amp;#160; This criteria includes the number of Actions provided (smaller numbers will favor the Task-per-Action approach, whereas larger will favor the ForEach approach) as well as whether ParallelOptions were provided to Invoke to control things like the degree of parallelism or cancellation.&lt;/p&gt;  &lt;p&gt;At the end of the day, it’s important to remember that implementation details may change at any time.&amp;#160; But having a good mental model for how something is implemented can also help to understand the constraints imposed by that functionality.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9641563" 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/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><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Beta/default.aspx">Beta</category></item><item><title>.NET 4 Cancellation Framework</title><link>http://blogs.msdn.com/pfxteam/archive/2009/05/22/9635790.aspx</link><pubDate>Sat, 23 May 2009 06:29:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9635790</guid><dc:creator>mikelid</dc:creator><slash:comments>24</slash:comments><comments>http://blogs.msdn.com/pfxteam/comments/9635790.aspx</comments><wfw:commentRss>http://blogs.msdn.com/pfxteam/commentrss.aspx?PostID=9635790</wfw:commentRss><wfw:comment>http://blogs.msdn.com/pfxteam/rsscomments.aspx?PostID=9635790</wfw:comment><description>&lt;P&gt;A very interesting addition to .NET 4 is a set of new types that specifically assist with building cancellation-aware applications and libraries. The new types enable rich scenarios for convenient and safe cancellation, and help simplify situations that used to be be difficult and error-prone and non-composable.&lt;/P&gt;
&lt;P&gt;The details of the new types are described below, but lets begin with some of the motivating principles that the new types were designed to support: &lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;When any unit of work is commenced, it should have a consistent means to support early termination in response to a cancellation request. &lt;/LI&gt;
&lt;LI&gt;If some unit of work controls various other moving pieces, it should be able to conveniently chain cancellation requests to them. &lt;/LI&gt;
&lt;LI&gt;Blocking calls should be able to support cancellation. &lt;/LI&gt;
&lt;LI&gt;Calls to complex operations, such as MoveNext() on a PLINQ enumerator, should have simple yet comprehensive cancellation support. &lt;/LI&gt;
&lt;LI&gt;When infrastructure makes calls back to potentially long-running user code, it should be possible for the user code to observe and respond to cancellation requests in a cooperative fashion. &lt;/LI&gt;
&lt;LI&gt;Cancellation should be an obvious part of an API with clean and consistent semantics. &lt;/LI&gt;
&lt;LI&gt;Cancellation should not be forceful but instead cooperative.&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;In many prevailing systems, cancellation has been a secondary feature that rarely gets treated in sufficient detail to enable all of the above principles in a comprehensive fashion. The new types introduced to .NET 4 raise cancellation to be a primary concept for .NET APIs and one that can be cleanly and easily incorporated into any system.&lt;/P&gt;
&lt;H3&gt;Previous approaches&lt;/H3&gt;
&lt;P&gt;Cancellation is a feature that finds its way into many APIs and applications either by design or by necessity. An interesting classification of common approaches is Herb Sutter's article &lt;A href="http://www.ddj.com/hpc-high-performance-computing/207100682" mce_href="http://www.ddj.com/hpc-high-performance-computing/207100682"&gt;"Interrupt Politely"&lt;/A&gt;, which outlines four distinct techniques. Those four techniques can be distilled down to the two major techniques: The first is to use asynchronous, forced cancellation such as thread-abort, process-kill, or AppDomain-unload. Any asynchronous technique has the common trait that the target of cancellation is caught completely unaware and cannot easily ensure data safety. For many reasons, but particularly due to the risk of partial updates to shared data, the use of asynchronous techniques is strongly discouraged.&lt;/P&gt;
&lt;P&gt;The second general technique is cooperative whereby a request for cancellation is communicated to the target in some manner and the target of cancellation observes and enacts the request itself. This is inherently safer, but it does require that all targets of cancellation are fully participating in the process. The most commonly implemented style for this approach involves every potential target object tracking some state that represents whether cancellation has been requested although as we shall see this has some inherent problems and can be improved.&lt;/P&gt;
&lt;P&gt;.NET libraries in general follow the cooperative approach and various examples can be found; for example, the BackgroundWorker class in Windows Forms has a member called CancellationPending which is set to true by calling the method &lt;BR&gt;BackgroundWorker.CancelAsync(). Similarly, the classes based on System.Net.WebRequest provide an Abort() method to cancel the current operation and prevent further operations from commencing. A BackgroundWorker has a clear notion of the work that should be canceled, but a WebRequest may have either an active GetResponse() or GetRequestStream() call, and so the target of the cancellation request is not as clear. More generally, if a single object can be used to run distinct operations or if it can run many operations simultaneously, then it becomes very awkward to track cancellation requests on the object itself. And if the object allows the cancellation request to be reset either before or after enactment of a cancellation request, then there are inherent race conditions that can lead to subtle problems.&lt;/P&gt;
&lt;P&gt;So although cooperative cancellation is far superior to asynchronous cancellation, the common approach has the following issues:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Data is often imbued with a notion of cancellation, and this is a problematic abstraction. A better model is that specific occurrences of an &lt;I&gt;operation&lt;/I&gt; may be cancelable, but data is just data. &lt;/LI&gt;
&lt;LI&gt;Cancellation achieved by direct calls to Cancel() and Abort() methods on specific targets is not groupable or chainable. &lt;/LI&gt;
&lt;LI&gt;It is often necessary to perform some work in addition to setting a Boolean flag when enacting cancellation, but this support is not standardized or ubiquitous. &lt;/LI&gt;
&lt;LI&gt;If an operation on an object makes a callback to user code, it is often awkward to forward the cancellation request made on the parent object to the user code. &lt;/LI&gt;
&lt;LI&gt;If a class tracks cancellation state but allows multiple concurrent operations, or if it allows operations to commence after an earlier operation was canceled , then race-conditions become an inherent issue that frequently leads to subtle bugs. &lt;/LI&gt;
&lt;LI&gt;When cancellation is requested, identified and enacted, the resulting behaviors are not consistent. Some methods return as if nothing happened, some throw OperationCanceledException, some throw custom exceptions, and some return a custom error code. &lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;It is to address these issues that .NET 4 introduces a new approach to cooperative cancellation. And as we will examine in a future blog post, this approach is perfectly suited to the needs of Parallel Extensions and has been adopted across all our types.&lt;/P&gt;
&lt;H3&gt;New cancellation types&lt;/H3&gt;
&lt;P&gt;The new types provide a cooperative cancellation framework that is rich and general purpose. Some specific design principles of the new approach are:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Only specific framework types should represent a request for cancellation. &lt;/LI&gt;
&lt;LI&gt;Long-running or blocking methods should accept an explicit parameter that will inform the method of a cancellation request.&amp;nbsp; This is in contrast to mechanisms whereby operations automatically attach themselves to an &lt;EM&gt;ambient&lt;/EM&gt; cancellation-request object, such as one that has been stashed in thread-local-storage. Mechanisms that involve automatic discovery and attachment generally become awkward when the exact specification of the rules are fleshed out. &lt;/LI&gt;
&lt;LI&gt;The response made when cancellation is enacted should be to throw a consistent exception type. &lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;Two new types form the basis of the framework: A &lt;EM&gt;CancellationToken&lt;/EM&gt; is a struct that represents a ‘potential request for cancellation’. This struct is passed into method calls as a parameter and the method can poll on it or register a callback to be fired when cancellation is requested. A &lt;EM&gt;CancellationTokenSource &lt;/EM&gt;is a class that provides the mechanism for initiating a cancellation request and it has a Token property for obtaining an associated token. It would have been natural to combine these two classes into one, but this design allows the two key operations (initiating a cancellation request vs. observing and responding to cancellation) to be cleanly separated. In particular, methods that take only a CancellationToken can observe a cancellation request but cannot initiate one.&lt;/P&gt;
&lt;P&gt;When a call is made to CancellationTokenSource.Cancel(), the IsCancellationRequested property of any associated CancellationToken will become true and methods can poll on this to observe the cancellation request. If polling is not possible or not convenient, a callback can be attached via CancellationToken.Register(). A CancellationToken can be copied and passed around and all the copies will simply point back to the original CancellationTokenSource which holds all the actual state regarding cancellation requests, callback lists, etc.&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/pfxteam/WindowsLiveWriter/NET4.0CancellationFramework_A897/image_4.png" mce_href="http://blogs.msdn.com/blogfiles/pfxteam/WindowsLiveWriter/NET4.0CancellationFramework_A897/image_4.png"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: block; FLOAT: none; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-LEFT: auto; BORDER-LEFT-WIDTH: 0px; MARGIN-RIGHT: auto" title=image border=0 alt=image src="http://blogs.msdn.com/blogfiles/pfxteam/WindowsLiveWriter/NET4.0CancellationFramework_A897/image_thumb_1.png" width=480 height=153 mce_src="http://blogs.msdn.com/blogfiles/pfxteam/WindowsLiveWriter/NET4.0CancellationFramework_A897/image_thumb_1.png"&gt;&lt;/A&gt;When methods see that CancellationToken.IsCancellationRequested == true, they should respond to this by throwing an OperationCanceledException(cancellationToken). Throwing this exception communicates that the method finished without fully completing its stated purpose and states which CancellationToken it observed. Note that the existing OperationCanceledException class has been augmented with constructors and a property for CancellationToken.&lt;/P&gt;
&lt;P&gt;We can now look at some specific examples: the first example shows how to create a CancellationTokenSource, pass its associated CancellationToken to a method, and how to poll on that token and correctly throw an OperationCanceledException. Note that cancellation doesn't need to be checked after every single statement, but it might be checked once per few thousand instructions or so. A general guideline is that cancellation should be checked as frequently as possible subject only to avoiding significant performance impact. Because polling on ct.IsCancellationRequested is very cheap (a single volatile read and a handful of IL instructions), cancellation can be tested frequently without a significant performance impact.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT size=2 face=Consolas&gt;EventHandler externalEvent; &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;void Example1() &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;{ &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; CancellationTokenSource cts = new CancellationTokenSource(); &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; externalEvent += &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (sender, obj) =&amp;gt; { cts.Cancel(); }; //wire up an external requester &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; try &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int val = LongRunningFunc(cts.Token); &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; catch (OperationCanceledException) &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //cleanup after cancellation if required... &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2 face=Consolas&gt;private static int LongRunningFunc(CancellationToken token) &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;{ &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; int total = 0; &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; for(int i=0; i&amp;lt;1000; i++){ &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (int j = 0; j &amp;lt; 1000; j++) &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; total++; &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(token.IsCancellationRequested){ // observe cancellation &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new OperationCanceledException(token); // acknowledge cancellation &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; return total; &lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;The second example demonstrates using the callback facility on CancellationToken for when polling is not an option.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT size=2 face=Consolas&gt;void BlockingOperation(CancellationToken token) &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;{ &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; ManualResetEvent mre = new ManualResetEvent(false); &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; //register a callback that will set the MRE &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; CancellationTokenRegistration registration = &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; token.Register(() =&amp;gt; mre.Set()); &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; using (registration) &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mre.WaitOne(); &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (token.IsCancellationRequested) //did cancellation wake us? &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new OperationCanceledException(token); &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; } //dispose the registration, which performs the deregisteration. &lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;A common pattern in these situations is to use the callback to force whatever condition the blocking call is waiting on, and then immediately check to see if cancellation was the reason the blocking call was woken. Although there is a race condition here that normal waking may occur just before a cancellation request is made, this race is benign as it is always safe to respond to the cancellation request regardless of why the wait finished.&lt;/P&gt;
&lt;P&gt;The third example shows how to listen for cancellation via a regular WaitHandle. Under the covers, CancellationToken.WaitHandle is a lazily-allocated ManualResetEvent that becomes set when cancellation is requested.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT size=2 face=Consolas&gt;void Wait(WaitHandle wh, CancellationToken token) &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;{ &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; WaitHandle.WaitAny(new [] {wh, token.WaitHandle}); &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; if (token.IsCancellationRequested) //did cancellation wake us? &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new OperationCanceledException(token); &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;And finally, the fourth example shows running multiple asynchronous operations which share a common CancellationToken.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT size=2 face=Consolas&gt;void Example4() &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;{ &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; CancellationTokenSource cts = new CancellationTokenSource(); &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; StartAsyncFunc1(cts.Token); &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; StartAsyncFunc2(cts.Token); &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; StartAsyncFunc3(cts.Token); &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; //... &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; cts.Cancel(); // all listeners see the same cancellation request. &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;In particular it is interesting to note that each of the asynchronous functions might pass on the token to other methods and that everyone who is observing the token (or copies of the token) will see the cancellation request when cts.Cancel() is called. &lt;BR&gt;&lt;/P&gt;
&lt;H3&gt;Details&lt;/H3&gt;
&lt;P&gt;A few details are important for an understanding of the new approach.&lt;/P&gt;
&lt;P&gt;A CancellationTokenSource may transition from non-canceled only once and cannot be reset. This prevents various race-conditions that arise deep inside method calls if reset were permitted. At an application level, however, reset functionality is often required and this is achieved by creating a new CancellationTokenSource to replace a used one.&lt;/P&gt;
&lt;P&gt;A CancellationToken is a lightweight struct that includes only a single reference back to a CancellationTokenSource. As such, it is the same ‘weight’ as a normal object reference, but because it is a separate type, it can have its own API than provides only read operations.&lt;/P&gt;
&lt;P&gt;When a callback is registered to a CancellationToken, the current thread's ExecutionContext is captured so that the callback will be run with the the exact same security context . The capturing of the current thread's synchronization context is optional can be requested via an overload of ct.Register() if required. Callbacks are normally stored and then run when cancellation is requested, but if a callback is registered after cancellation has been requested, the callback will run immediately on the current thread, or via Send() on the current SynchronizationContext if applicable.&lt;/P&gt;
&lt;P&gt;When a callback is registered to a CancellationToken, the returned object is a CancellationTokenRegistration. This is a light struct type that is IDiposable, and disposing this registration object causes the callback to be deregistered. A guarantee is made that after the Dispose() method has returned, the registered callback is neither running nor will subsequently commence. A consequence of this is that CancellationTokenRegistration.Dispose()must block if the callback is currently executing. Hence, all registered callbacks should be fast and not block for any significant duration. &lt;BR&gt;&lt;/P&gt;
&lt;H3&gt;Advanced patterns&lt;/H3&gt;
&lt;P&gt;To finish this introduction to the new cancellation framework we can look briefly at two more advanced patterns of usage.&lt;/P&gt;
&lt;P&gt;One situation that arises is that some methods wish to observe two separate tokens. The best approach here is to create a linked CancellationTokenSource that will be signaled if either of the source tokens has become signaled.&lt;/P&gt;
&lt;P align=center&gt;&lt;A href="http://blogs.msdn.com/blogfiles/pfxteam/WindowsLiveWriter/NET4.0CancellationFramework_A897/image_6.png" mce_href="http://blogs.msdn.com/blogfiles/pfxteam/WindowsLiveWriter/NET4.0CancellationFramework_A897/image_6.png"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=image border=0 alt=image src="http://blogs.msdn.com/blogfiles/pfxteam/WindowsLiveWriter/NET4.0CancellationFramework_A897/image_thumb_2.png" width=480 height=126 mce_src="http://blogs.msdn.com/blogfiles/pfxteam/WindowsLiveWriter/NET4.0CancellationFramework_A897/image_thumb_2.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;The method CancellationTokenSource.CreateLinkedTokenSource() is specifically designed to assist with this and registers the callbacks as required. For example:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT size=2 face=Consolas&gt;void LinkingExample(CancellationToken ct1, CancellationToken ct2) &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;{ &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; CancellationTokenSource linkedCTS = &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; CancellationTokenSource.CreateLinkedTokenSource(ct1, ct2); &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; try &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SlowFunc(linkedCTS.Token); &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; catch(OperationCanceledException oce) &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (ct1.IsCancellationRequested) &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ... &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else if (ct2.IsCancellationRequested) &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ... &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; linkedCTS.Dispose(); // clean up the linking. required. &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;By using cancellation linking, cancellation-aware methods need only take one CancellationToken parameter. Be aware however that because linking attaches callbacks onto the source tokens, it is very important to clean up properly, otherwise linkedCTS and the callback delegates cannot be garbage collected until the linked sources are also available for collection. This is achieve by explicitly disposing linkedCTS, or via the using() pattern.&lt;/P&gt;
&lt;P&gt;Another scenario that arises is to allow library code and user code to cooperate when responding to cancellation. Consider a library method that accepts a CancellationToken, and then calls back to user code. If the user code responds to a cancellation request, it wants to communicate this cleanly to the library code. This is achieved by the user code throwing an OperationCanceledException that mentions the same CancellationToken that the library code was given. Typically the user code will know about the same CancellationToken by getting it through some side channel, e.g. via closure-capture, rather than the library method explicitly passing it on. For example:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT size=2 face=Consolas&gt;private void RunQuery() &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;int[] data = {1,2,3}; &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; CancellationTokenSource cts = new CancellationTokenSource(); &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; var query = data.AsParallel() &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&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; .WithCancellation(cts.Token) // token given to library code &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&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; .Select( (x) =&amp;gt; SlowFunc(x, cts.Token) ); // token passed to user code &lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2 face=Consolas&gt;private int SlowFunc(int x, CancellationToken token) &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;{ &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; int result &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; while(...) &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (token.IsCancellationRequested) &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new OperationCanceledException(token); &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ... &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&amp;nbsp;&amp;nbsp; return result; &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Notice that the library function (in this case a PLINQ query) and the user code are both observing the same token and that the user-code throws an OperationCanceledException that mentions this common token. This allows the library code to see that the user code has performed cooperative cancellation and has not simply thrown some arbitrary exception. The library may respond to this by behaving exactly as though it had seen the cancellation request itself, rather than thinking the user code failed unexpectedly. It also has the advantage that if the user code throws an OperationCanceledException for some unexpected reason (and mentions a different token or no token at all), it will not be mistakenly interpreted as cooperative cancellation. Because the token is tracked in the OperationCanceledException itself, there is no confusion about the reason for the exception being thrown.&lt;/P&gt;
&lt;H3&gt;Conclusion&lt;/H3&gt;
&lt;P&gt;The new cancellation types introduced to .NET 4 provide a new framework for building systems that have rich and consistent cancellation behaviors. This will specifically assist with GUIs, applications, and libraries that manage long running or blocking operations. Over time we expect to see more libraries migrate to this approach and reduce the variation and issues inherent in the current crop of cancellation solutions. Applications and 3rd-party libraries can use these new types to interoperate cleanly with Parallel Extensions and for their own purposes.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9635790" width="1" height="1"&gt;</description><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/Coordination+Data+Structures/default.aspx">Coordination Data Structures</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/CDS/default.aspx">CDS</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/.NET+4.0/default.aspx">.NET 4.0</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Beta/default.aspx">Beta</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Cancellation/default.aspx">Cancellation</category></item><item><title>Samples for Parallel Programming with the .NET Framework 4</title><link>http://blogs.msdn.com/pfxteam/archive/2009/05/20/9633116.aspx</link><pubDate>Thu, 21 May 2009 03:36:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9633116</guid><dc:creator>toub</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/pfxteam/comments/9633116.aspx</comments><wfw:commentRss>http://blogs.msdn.com/pfxteam/commentrss.aspx?PostID=9633116</wfw:commentRss><wfw:comment>http://blogs.msdn.com/pfxteam/rsscomments.aspx?PostID=9633116</wfw:comment><description>&lt;P&gt;Along with the release of the &lt;A href="http://blogs.msdn.com/pfxteam/archive/2009/05/20/9632991.aspx" mce_href="http://blogs.msdn.com/pfxteam/archive/2009/05/20/9632991.aspx"&gt;.NET Framework 4 Beta 1&lt;/A&gt;, we've just published a slew of samples that demonstrate using Parallel Extensions in a variety of ways.&amp;nbsp; You can download these from Code Gallery at &lt;A href="http://code.msdn.microsoft.com/ParExtSamples"&gt;http://code.msdn.microsoft.com/ParExtSamples&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;These samples include raytracers, a sudoku game, an image colorization algorithm, solvers for the n-queens problem, fractal image generators, and more.&amp;nbsp; The samples include code written to use Parallel Extensions from C#, Visual Basic, F#, and C++/CLI.&amp;nbsp; They include examples of using the Task Parallel Library, PLINQ, new coordination data structures, and even databinding a WPF UI to a collection that has data stored into it&amp;nbsp;from a&amp;nbsp;background thread.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;On top of all of this, the samples include a project called "Parallel Extensions Extras", which features a healthy portion of extension methods for .NET 4 types, new data structures to augment what's being shipped in .NET 4, custom schedulers for TPL, and lots of other goodness.&amp;nbsp; Definitely worth a perusal.&lt;/P&gt;
&lt;P&gt;Enjoy!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9633116" 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/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/F_2300_/default.aspx">F#</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/CDS/default.aspx">CDS</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><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Beta/default.aspx">Beta</category></item><item><title>.NET 4 MSDN documentation for parallelism</title><link>http://blogs.msdn.com/pfxteam/archive/2009/05/20/9633092.aspx</link><pubDate>Thu, 21 May 2009 01:59:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9633092</guid><dc:creator>toub</dc:creator><slash:comments>7</slash:comments><comments>http://blogs.msdn.com/pfxteam/comments/9633092.aspx</comments><wfw:commentRss>http://blogs.msdn.com/pfxteam/commentrss.aspx?PostID=9633092</wfw:commentRss><wfw:comment>http://blogs.msdn.com/pfxteam/rsscomments.aspx?PostID=9633092</wfw:comment><description>&lt;P&gt;In addition to the Betas of Visual Studio 2010 and the .NET Framework 4 being &lt;A href="http://msdn.microsoft.com/en-us/vstudio/dd582936.aspx" mce_href="http://msdn.microsoft.com/en-us/vstudio/dd582936.aspx"&gt;available for download&lt;/A&gt; today, the MSDN documentation for .NET 4 Beta 1 is also available.&amp;nbsp; This includes quite a bit of useful information about the new parallelism constructs.&amp;nbsp; Here's a summary of the relevant material, with links:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/dd460693(VS.100).aspx" mce_href="http://msdn.microsoft.com/en-us/library/dd460693(VS.100).aspx"&gt;Parallel Programming in the .NET Framework&lt;/A&gt;&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/dd460717(VS.100).aspx" mce_href="http://msdn.microsoft.com/en-us/library/dd460717(VS.100).aspx"&gt;Task Parallel Library&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/dd460688(VS.100).aspx" mce_href="http://msdn.microsoft.com/en-us/library/dd460688(VS.100).aspx"&gt;Parallel LINQ&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/dd460718(VS.100).aspx" mce_href="http://msdn.microsoft.com/en-us/library/dd460718(VS.100).aspx"&gt;Data Structures for Parallel Programming&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;Parallel Diagnostic Tools&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/dd537632(VS.100).aspx" mce_href="http://msdn.microsoft.com/en-us/library/dd537632(VS.100).aspx"&gt;Thread Execution Data Views&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/dd554943(VS.100).aspx" mce_href="http://msdn.microsoft.com/en-us/library/dd554943(VS.100).aspx"&gt;Walkthrough: Debugging a Parallel Application&lt;/A&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;/UL&gt;
&lt;LI&gt;.NET Framework Class Library&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/system(VS.100).aspx" mce_href="http://msdn.microsoft.com/en-us/library/system(VS.100).aspx"&gt;System Namespace&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/system.collections.concurrent(VS.100).aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.collections.concurrent(VS.100).aspx"&gt;System.Collections.Concurrent Namespace&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/system.linq(VS.100).aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.linq(VS.100).aspx"&gt;System.Linq Namespace&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/system.threading(VS.100).aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.threading(VS.100).aspx"&gt;System.Threading Namespace&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/system.threading.tasks(VS.100).aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.threading.tasks(VS.100).aspx"&gt;System.Threading.Tasks Namespace&lt;/A&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;/UL&gt;
&lt;P&gt;Related to this and for more background information, you can also check out the documentation for our &lt;EM&gt;native&lt;/EM&gt; concurrency runtime and programming models:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/dd504870(VS.100).aspx" mce_href="http://msdn.microsoft.com/en-us/library/dd504870(VS.100).aspx"&gt;Concurrency Runtime&lt;/A&gt;&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/dd492418(VS.100).aspx" mce_href="http://msdn.microsoft.com/en-us/library/dd492418(VS.100).aspx"&gt;Parallel Pattern Library&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/dd492627(VS.100).aspx" mce_href="http://msdn.microsoft.com/en-us/library/dd492627(VS.100).aspx"&gt;Asynchronous Agents Library&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/dd492638(VS.100).aspx" mce_href="http://msdn.microsoft.com/en-us/library/dd492638(VS.100).aspx"&gt;Synchronization Data Structures&lt;/A&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;Reference&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/dd492819(VS.100).aspx" mce_href="http://msdn.microsoft.com/en-us/library/dd492819(VS.100).aspx"&gt;Concurrency Namespace&lt;/A&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;/UL&gt;
&lt;P&gt;As with the actual bits, any and all feedback on the docs is welcome and encouraged.&amp;nbsp; A great place to provide feedback is on the forums, for managed at &lt;A href="http://social.msdn.microsoft.com/Forums/en-US/parallelextensions/threads"&gt;http://social.msdn.microsoft.com/Forums/en-US/parallelextensions/threads&lt;/A&gt;&amp;nbsp;and for native at &lt;A href="http://social.msdn.microsoft.com/Forums/en-US/parallelcppnative/threads"&gt;http://social.msdn.microsoft.com/Forums/en-US/parallelcppnative/threads&lt;/A&gt;.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9633092" width="1" height="1"&gt;</description><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><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Beta/default.aspx">Beta</category></item><item><title>.NET 4 Beta 1 is now available, with parallelism!</title><link>http://blogs.msdn.com/pfxteam/archive/2009/05/20/9632991.aspx</link><pubDate>Thu, 21 May 2009 01:38:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9632991</guid><dc:creator>toub</dc:creator><slash:comments>18</slash:comments><comments>http://blogs.msdn.com/pfxteam/comments/9632991.aspx</comments><wfw:commentRss>http://blogs.msdn.com/pfxteam/commentrss.aspx?PostID=9632991</wfw:commentRss><wfw:comment>http://blogs.msdn.com/pfxteam/rsscomments.aspx?PostID=9632991</wfw:comment><description>&lt;P&gt;We’re very excited that the .NET Framework 4 Beta is now available for public download, as .NET 4 has Parallel Extensions built into its core. You can download the Betas for Visual Studio 2010 and .NET Framework 4 at &lt;A title=http://msdn.microsoft.com/en-us/netframework/dd582936.aspx href="http://msdn.microsoft.com/en-us/netframework/dd582936.aspx" mce_href="http://msdn.microsoft.com/en-us/netframework/dd582936.aspx"&gt;http://msdn.microsoft.com/en-us/netframework/dd582936.aspx&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;For more information on what’s new in Beta 1 regarding concurrency and parallelism, here are some useful links:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="http://blogs.msdn.com/pfxteam/archive/2009/04/29/9576291.aspx" mce_href="http://blogs.msdn.com/pfxteam/archive/2009/04/29/9576291.aspx"&gt;What’s new in Beta 1 for Parallel LINQ (PLINQ)?&lt;/A&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://blogs.msdn.com/pfxteam/archive/2009/03/27/9514938.aspx" mce_href="http://blogs.msdn.com/pfxteam/archive/2009/03/27/9514938.aspx"&gt;What’s new in Beta 1 for the Task Parallel Library? (Part 1/3)&lt;/A&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://blogs.msdn.com/pfxteam/archive/2009/04/06/9534426.aspx" mce_href="http://blogs.msdn.com/pfxteam/archive/2009/04/06/9534426.aspx"&gt;What’s new in Beta 1 for the Task Parallel Library? (Part 2/3)&lt;/A&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://blogs.msdn.com/pfxteam/archive/2009/04/14/9549246.aspx" mce_href="http://blogs.msdn.com/pfxteam/archive/2009/04/14/9549246.aspx"&gt;What’s new in Beta 1 for the Task Parallel Library? (Part 3/3)&lt;/A&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://blogs.msdn.com/pfxteam/archive/2009/05/15/9621187.aspx" mce_href="http://blogs.msdn.com/pfxteam/archive/2009/05/15/9621187.aspx"&gt;Debugging Support for Tasks&lt;/A&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://www.danielmoth.com/Blog/2009/05/parallel-stacks-another-new-vs2010.html" mce_href="http://www.danielmoth.com/Blog/2009/05/parallel-stacks-another-new-vs2010.html"&gt;Parallel&amp;nbsp;Stacks – another new VS2010 debugger window&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://blogs.msdn.com/pfxteam/archive/2009/03/04/9457880.aspx" mce_href="http://blogs.msdn.com/pfxteam/archive/2009/03/04/9457880.aspx"&gt;What’s new in Beta 1 for the coordination data structures?&lt;/A&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://blogs.msdn.com/ericeil/archive/2009/04/23/clr-4-0-threadpool-improvements-part-1.aspx" mce_href="http://blogs.msdn.com/ericeil/archive/2009/04/23/clr-4-0-threadpool-improvements-part-1.aspx"&gt;CLR 4.0 ThreadPool Improvements: Part 1&lt;/A&gt; &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;As you may have noticed, this blog has been a bit quiet as we’ve been getting ready for the Beta.&amp;nbsp; Now that it’s here, you can expect us to be blogging quite frequently over the next days, weeks, and months.&amp;nbsp; If there are specific topics you’d like to see discussed, please do let us know.&amp;nbsp; And most importantly, we’re still extremely interested in your feedback, so any comments, questions, praises, criticisms, or suggestions you have should certainly be sent our way.&amp;nbsp; The best place to do so is on the &lt;A href="http://social.msdn.microsoft.com/Forums/en-US/parallelextensions/threads" mce_href="http://social.msdn.microsoft.com/Forums/en-US/parallelextensions/threads"&gt;forums&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;Enjoy!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9632991" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/pfxteam/archive/tags/.NET+4.0/default.aspx">.NET 4.0</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Beta/default.aspx">Beta</category></item><item><title>What’s new in Beta 1 for Parallel LINQ (PLINQ)?</title><link>http://blogs.msdn.com/pfxteam/archive/2009/04/29/9576291.aspx</link><pubDate>Wed, 29 Apr 2009 21:54:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9576291</guid><dc:creator>essey</dc:creator><slash:comments>24</slash:comments><comments>http://blogs.msdn.com/pfxteam/comments/9576291.aspx</comments><wfw:commentRss>http://blogs.msdn.com/pfxteam/commentrss.aspx?PostID=9576291</wfw:commentRss><wfw:comment>http://blogs.msdn.com/pfxteam/rsscomments.aspx?PostID=9576291</wfw:comment><description>&lt;P&gt;A number of improvements have been made to Parallel Extensions since the Visual Studio 2010 CTP across the Task Parallel Library (TPL), Parallel LINQ (PLINQ), and our coordination data structures.&amp;nbsp; You can find the latest on TPL (&lt;A href="http://blogs.msdn.com/pfxteam/archive/2009/03/27/9514938.aspx" mce_href="http://blogs.msdn.com/pfxteam/archive/2009/03/27/9514938.aspx"&gt;1&lt;/A&gt; &lt;A href="http://blogs.msdn.com/pfxteam/archive/2009/04/06/9534426.aspx" mce_href="http://blogs.msdn.com/pfxteam/archive/2009/04/06/9534426.aspx"&gt;2&lt;/A&gt; &lt;A href="http://blogs.msdn.com/pfxteam/archive/2009/04/14/9549246.aspx" mce_href="http://blogs.msdn.com/pfxteam/archive/2009/04/14/9549246.aspx"&gt;3&lt;/A&gt;) and the data structures (&lt;A href="http://blogs.msdn.com/pfxteam/archive/2009/03/04/9457880.aspx" mce_href="http://blogs.msdn.com/pfxteam/archive/2009/03/04/9457880.aspx"&gt;link&lt;/A&gt;) on this blog.&amp;nbsp; Here are the big changes to PLINQ since that CTP:&lt;B&gt;&lt;/B&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;With- Operators Pattern &lt;/LI&gt;
&lt;LI&gt;Execution Mode &lt;/LI&gt;
&lt;LI&gt;Cancellation &lt;/LI&gt;
&lt;LI&gt;Custom Partitioning &lt;/LI&gt;
&lt;LI&gt;Refactoring &lt;/LI&gt;
&lt;LI&gt;Merge Options &lt;/LI&gt;
&lt;LI&gt;AsMerged Renamed Back to AsSequential &lt;/LI&gt;
&lt;LI&gt;Binary Operators Now Require AsParallel on Both Sides &lt;/LI&gt;
&lt;LI&gt;Performance Improvements &lt;/LI&gt;
&lt;LI&gt;Removed Seldom Used Operators &lt;/LI&gt;&lt;/UL&gt;
&lt;H2&gt;&lt;B&gt;With- Operators Pattern&lt;/B&gt;&lt;/H2&gt;
&lt;P&gt;To parameterize PLINQ, we have added a set of controls beginning with With-.&amp;nbsp; As we began to add controls to PLINQ, it became clear that pretty soon the number of overloads on AsParallel, Range, and Repeat would increase dramatically.&amp;nbsp; This pattern resolves that and increases readability. Compare:&lt;/P&gt;
&lt;P&gt;OLD: e.AsParallel(4)&lt;/P&gt;
&lt;P&gt;NEW: e.AsParallel().WithDegreeOfParallelism(4)&lt;/P&gt;
&lt;P&gt;The With- methods are currently:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;WithDegreeOfParallelism &lt;/LI&gt;
&lt;LI&gt;WithExecutionMode (see Execution Mode below) &lt;/LI&gt;
&lt;LI&gt;WithCancellation&amp;nbsp; (see Cancellation below) &lt;/LI&gt;
&lt;LI&gt;WithMergeOptions (see Merge Options below) &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;The latter 3 have their own sections below.&lt;/P&gt;
&lt;H2&gt;Execution Mode&lt;/H2&gt;
&lt;P&gt;PLINQ does its best to ensure that it will never behave much worse than LINQ-to-Objects.&amp;nbsp; For example, if a LINQ-to-Objects query needs a constant amount of memory to execute, PLINQ also aims to use only a constant amount of memory on the same query.&amp;nbsp; Or, if a LINQ-to-Objects query has low overhead per element processed, the PLINQ query should also have low overhead per element.&amp;nbsp; If PLINQ cannot meet these constraints by executing the query in parallel, it will execute the query sequentially.&lt;/P&gt;
&lt;P&gt;Note that while the goal will be to never do much worse than LINQ to Objects, it is very unlikely that we will be able to achieve that goal for all queries. One suggestion that comes up regularly is to use a smart algorithm that does some sort of time measurements and switches back and forth between parallel and sequential execution. This is significantly more problematic in practice than it may sound, and we have no plans in this direction for V1.&lt;/P&gt;
&lt;P&gt;PLINQ makes this decision solely based on query shape.&amp;nbsp; It does not look into size of the data set or execution time of the delegates.&amp;nbsp; If you believe that you will not see speedup in your query, consider comparing the versions of the query with and without AsParallel.&amp;nbsp; Queries that will execute sequentially in the conservative mode include:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Queries contain indexed Select, indexed Where, indexed SelectMany, or ElementAt in a position where the indices are no longer in the original order. Index ordering is senstive to operators that change ordering (e.g. OrderBy) and operators that remove elements (e.g. Where). &lt;/LI&gt;
&lt;LI&gt;Queries that contain operators Take, TakeWhile, Skip, SkipWhile when indices are not in the original order (see above bullet). &lt;/LI&gt;
&lt;LI&gt;Queries that contain Zip, SequenceEquals, unless one of the data sources has an originally ordered index and the other data source is indexible (i.e. an array or IList&amp;lt;T&amp;gt;). &lt;/LI&gt;
&lt;LI&gt;Queries that contain Concat, unless it is applied to indexible data sources. &lt;/LI&gt;
&lt;LI&gt;Queries that contain Reverse, unless applied to an indexible data source. &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;A certain class of operators require the data to be partitioned with matching data, this is best achieved through hash-partitioning. Our other partitioning types (chunk, range, and striped) would not organize this data correctly for matching. These operators include Join, GroupBy, GroupJoin, Distinct, Union, Intersect, and Except. As for hash-partitioning operators From the data that we have, it seems that our hash-partitioning operators do not get much of a speedup, but do not inhibit it too drastically either. So, at least presently, hash-partitioning operators will not cause a query to execute sequentially (in the conservative mode). This allows for speedup when these operators combine with other operators.&lt;/P&gt;
&lt;P&gt;The ParallelExecutionMode enum is added to the System.Linq namespace. It has Default and ForceParallelism values. If you believe that your query can in fact get speedup, but that we’re currently dropping back to sequential, write your query as 
&lt;TABLE border=1 cellSpacing=0 cellPadding=0&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=638&gt;
&lt;P&gt;e.AsParallel().WithExecutionMode(ParallelExecutionMode.ForceParallelism)....&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;/P&gt;
&lt;P&gt;to override PLINQ’s conservative behavior.&lt;/P&gt;
&lt;P&gt;Over time, we will likely be able to support more and more query shapes, so please let us know which ones are important to you so that we can consider them for perf tuning.&lt;/P&gt;
&lt;H2&gt;Cancellation&lt;/H2&gt;
&lt;P&gt;Just as Tasks, Parallel, BlockingCollection, Barrier, CountdownEvent, ManualResetEventSlim, and SemaphoreSlim are plumbed for cancellation, so is PLINQ.&amp;nbsp; Cancellation patterns have been added to the .NET Framework 4.0, and our team has rebuilt our system on top of them to provide an elegant, common pattern to exit operations.&amp;nbsp; A dedicated topic on cancellation is coming soon, though we’ll jump in right here with how PLINQ uses the types.&lt;/P&gt;
&lt;P&gt;Preparie a query to allow cancellation by using WithCancellation on a query. Here’s an example usage pattern with Cancellation split between two query executions: &lt;/P&gt;
&lt;TABLE border=0 cellSpacing=0 cellPadding=2 width=533&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=531&gt;
&lt;P&gt;var cts = new CancellationTokenSource();&lt;/P&gt;
&lt;P&gt;var q = a.AsParallel().WithCancellation(cts.Token).Where(x=&amp;gt;Filter(x)).Select(x=&amp;gt;DoWork(x);&lt;/P&gt;
&lt;P&gt;-- separate thread --&lt;/P&gt;
&lt;P&gt;foreach (var e in q) { … }&amp;nbsp; // Statement 1&lt;/P&gt;
&lt;P&gt;-- separate thread --&lt;/P&gt;
&lt;P&gt;var l = q.ToList(); // Statement 2&lt;/P&gt;
&lt;P&gt;-- separate thread --&lt;/P&gt;
&lt;P&gt;cts.Cancel(); // this will attempt to cancel any in-flight queries, &lt;/P&gt;
&lt;P&gt;// including both statements 1 and 2&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;Note on Dispose – Disposing the enumerator, as is done automatically by the foreach pattern, will also cancel the plinq work occurring in the background.&lt;/P&gt;
&lt;H2&gt;Custom Partitioning &lt;/H2&gt;
&lt;P&gt;There are some data types and data sources that PLINQ will not know the best way to partition.&amp;nbsp; PLINQ optimizes for general cases and common cases, but sometimes you want control over how the data can best be partitioned in PLINQ.&lt;/P&gt;
&lt;P&gt;So, the new Partitioner&amp;lt;TSource&amp;gt; abstract class, the new OrderablePartitioner&amp;lt;TSource&amp;gt; abstract class, and the new Partitioner factory classes have been created to allow you greater control over partitioning for increased performance.&amp;nbsp;&amp;nbsp;&amp;nbsp; For PLINQ, there are overload extension methods of AsParallel that will hook these types into PLINQ.&lt;/P&gt;
&lt;P&gt;This is a weighty topic and will have its own future post.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;&lt;B&gt;&lt;/B&gt;&lt;/P&gt;
&lt;H2&gt;Renamings and Refactorings&lt;/H2&gt;
&lt;P&gt;Because there was never an intent or reason for others to extend IParallelEnumerable, IParallelEnumerable&amp;lt;TSource&amp;gt;, nor IParallelOrderedEnumerable&amp;lt;TSource&amp;gt;, these have been changed from interfaces to abstract classes which cannot be extended.&amp;nbsp; This avoids the confusion on how they’re supposed to be used.&lt;/P&gt;
&lt;P&gt;&lt;B&gt;OLD –&amp;gt; &lt;/B&gt;&lt;B&gt;NEW&lt;/B&gt;&lt;/P&gt;
&lt;P&gt;IParallelEnumerable –&amp;gt;&amp;nbsp; ParallelQuery&lt;/P&gt;
&lt;P&gt;IParallelEnumerable&amp;lt;T&amp;gt; –&amp;gt; ParallelQuery&amp;lt;TSource&amp;gt;&lt;/P&gt;
&lt;P&gt;IParallelOrderedEnumerable&amp;lt;T&amp;gt; –&amp;gt; OrderedParallelQuery&amp;lt;TSource&amp;gt;&lt;/P&gt;
&lt;P&gt;While we were at it, we improved type names in generics, changing T –&amp;gt; TSource, and we ensured that all of the right extension methods were available for the non-generic ParallelQuery class.&lt;/P&gt;
&lt;H2&gt;ParallelMergeOptions&lt;/H2&gt;
&lt;P&gt;Handling of ParallelMergeOptions has been moved out of AsMerged.&amp;nbsp; Merge buffering is now specified via the&amp;nbsp; WithMergeOptions method.&lt;/P&gt;
&lt;H2&gt;AsMerged Renamed Back to AsSequential&lt;/H2&gt;
&lt;P&gt;In the last CTP we renamed AsSequential to AsMerged when we added an overload to take MergeOptions. Now, we renamed it back to AsSequential so that it would better pair with AsParallel.&lt;/P&gt;
&lt;H2&gt;Binary Operators Now Require AsParallel on Both Sides&lt;/H2&gt;
&lt;P&gt;We have changed the handling of the operators in LINQ which task 2 data sources to ensure that ordering expectations are more explicit.&amp;nbsp; There are a number of operators in LINQ which take 2 data sources. Here are those operators with overload counts in parentheses ():&amp;nbsp; Zip (1), Join (2), GroupJoin (2), Concat (1), SequenceEqual (2), Union (2), Intersect (2), Except (2). &lt;/P&gt;
&lt;P&gt;Some of these, such as SequenceEqual make no sense without ordering.&amp;nbsp; Others do make sense sense without ordering—and in fact, would be preferred this way—and some could go either way.&amp;nbsp; Rather than make all kinds of mystical decisions without involving you, steps have been taken for developers to make a decision.&lt;/P&gt;
&lt;P&gt;Previously, queries taking two input sequences could be parallelized as follows: 
&lt;TABLE border=1 cellSpacing=0 cellPadding=0&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=638&gt;
&lt;P&gt;a.AsParallel().AsOrdered().Zip(&lt;B&gt;b&lt;/B&gt;, (x, y) =&amp;gt; x*y);&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;/P&gt;
&lt;P&gt;These operators, of the form Operator(this ParallelQuery&amp;lt;T&amp;gt;, Enumerable&amp;lt;T&amp;gt;, ...), now throw a NotSupportedException at runtime and are marked as obsolete*.&lt;/P&gt;
&lt;P&gt;Now, to parallelize these queries, developers must choose: 
&lt;TABLE border=1 cellSpacing=0 cellPadding=0&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=638&gt;
&lt;P&gt;a.AsParallel().AsOrdered().Zip(&lt;B&gt;b.AsParallel()&lt;/B&gt;, (x, y) =&amp;gt; x*y);&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;/P&gt;
&lt;P&gt;OR 
&lt;TABLE border=1 cellSpacing=0 cellPadding=0&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=638&gt;
&lt;P&gt;a.AsParallel().AsOrdered().Zip(&lt;B&gt;b.AsParallel().AsOrdered()&lt;/B&gt;, (x, y) =&amp;gt; x*y);&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;/P&gt;
&lt;P&gt;* You may wonder why these operators are marked as obsolete during their introductory release. We did this to maintain parity with LINQ-to-Objects and other LINQ providers as much as possible. One of our primary design goals is to “Just add AsParallel” and you can see speedup. In this case, we wanted to have the same methods as in LINQ-to-Objects, but use the obosolete methods to encourage the addition of AsParallel on the second source as well.&lt;/P&gt;
&lt;H2&gt;Performance Improvements&lt;/H2&gt;
&lt;P&gt;A number of performance improvements have been undertaken, including:&lt;/P&gt;
&lt;P&gt;1. Order-preserving pipelining merges&lt;B&gt; &lt;/B&gt;– Previously, just putting AsOrdered on a query forced the entire query to execute before a single element is yielded.&amp;nbsp; This is now optimized so that elements from the query can be yielded as they are produced with Default (AutoBuffered) and NotBuffered values of MergeOptions.&lt;/P&gt;
&lt;P&gt;2. Improved partitioning fairness for data sources that don't implement IList&amp;lt;T&amp;gt;&lt;/P&gt;
&lt;P&gt;3. Better performance of some queries over IList&amp;lt;T&amp;gt; or an array&lt;/P&gt;
&lt;P&gt;4. Chunk partitioning size tuning - Chunk partitioning is the most common partitioning scheme for queries over data sources other that IList&amp;lt;T&amp;gt; and arrays (i.e. non-indexible data sources). The sizes of these chunks now grow as more and more chunks are accessed. This is to balance between the cases of a) queries with small data sets but expensive delegates in the queries and b) queries with large data sets but inexpensive delegates in the queries.&lt;/P&gt;
&lt;P&gt;5. Removal of likely false sharing cases, which have had up to 6x improvements in some cases&lt;/P&gt;
&lt;H2&gt;Removed Seldom Used Operators&lt;/H2&gt;
&lt;P&gt;A few PLINQ-specific operators that don’t really have use cases or existed simply for performance, yet did not show gains over existing LINQ operators, have been removed.&amp;nbsp; Reduced surface area allows us to focus more on the important stuff for you and lowers the count of concepts you need to know.&amp;nbsp;&amp;nbsp; If you don’t notice which ones, good!&lt;/P&gt;
&lt;P&gt;I hope that you enjoy using the Beta and send us lots of feedback!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9576291" 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/Beta/default.aspx">Beta</category></item></channel></rss>