<?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 : Parallel Extensions</title><link>http://blogs.msdn.com/pfxteam/archive/tags/Parallel+Extensions/default.aspx</link><description>Tags: Parallel Extensions</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>TaskCreationOptions.PreferFairness</title><link>http://blogs.msdn.com/pfxteam/archive/2009/07/07/9822857.aspx</link><pubDate>Tue, 07 Jul 2009 16:08:38 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9822857</guid><dc:creator>toub</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/pfxteam/comments/9822857.aspx</comments><wfw:commentRss>http://blogs.msdn.com/pfxteam/commentrss.aspx?PostID=9822857</wfw:commentRss><wfw:comment>http://blogs.msdn.com/pfxteam/rsscomments.aspx?PostID=9822857</wfw:comment><description>&lt;p&gt;One of the ways in which the Task Parallel Library achieves good performance is through “work-stealing”.&amp;#160; Work-stealing is supported in the &lt;a href="http://blogs.msdn.com/ericeil/archive/2009/04/23/clr-4-0-threadpool-improvements-part-1.aspx"&gt;.NET 4 ThreadPool&lt;/a&gt; for access through the Task Parallel Library and its default scheduler.&amp;#160; This manifests as every thread in the ThreadPool having its own queue for work; when that thread creates Tasks, by default these tasks are enqueued into the thread’s local queue, rather than into the global queue that a call to ThreadPool.QueueUserWorkItem would typically target.&amp;#160; When a thread goes in search for work to be executed, it starts with its local queue, an operation which enable some extra efficiencies due to improved cache locality, minimized contention, and so forth.&amp;#160; However, this logic also affects fairness.&lt;/p&gt;  &lt;p&gt;A typical thread pool will have a single queue that maintains all of the work to be executed.&amp;#160; When threads in the pool are ready to process another work item, they’ll dequeue the work from the head of the queue, and when new work arrives to be executed by the pool, it’ll be enqueued onto the queue’s tail.&amp;#160; This provides a level of fairness between work items, in that work items that arrive first are more likely to be picked off and start executing first.&lt;/p&gt;  &lt;p&gt;Work-stealing perturbs that fairness.&amp;#160; Threads external to the pool could be queuing up work, but if the threads in the pool are also generating work, the work generated by the pool will be preferred over the other work items, based on the search order employed by the threads in the pool (which start searching for work first with their local queues, only proceeding on to the global queue and then on to other threads’ queues if work wasn’t available locally).&amp;#160; This behavior is typically expected and even desired, in that if a work item being executed is generating more work, that generated work is typically considered part of the overall operation being processed, and thus it makes sense it would be preferred over other unrelated work.&amp;#160; For example, imagine a quicksort operation, where each recursive sort invocation potentially results in several further recursive calls; those calls, which in a parallel implementation are likely individual tasks, are part of the all-up sort operation.&lt;/p&gt;  &lt;p&gt;Still, there are some scenarios where this default behavior is inappropriate, where fairness should be maintained between particular work items generated by threads in the pool and work items generated by other threads.&amp;#160; This is often the case for long chains of continuations, where the work generated isn’t considered part of the current work but rather a follow-on to the current work.&amp;#160; In those cases, you may want that follow-on work to be prioritized in a fair manner with other work in the system.&amp;#160; This is where TaskCreationOptions.PreferFairness can prove useful.&lt;/p&gt;  &lt;p&gt;When a Task is scheduled to the default scheduler, the scheduler looks to see whether the current thread from which the Task is being queued is a ThreadPool thread that has its own local queue.&amp;#160; If it isn’t, the work item will be queued to the global queue.&amp;#160; If it is, the scheduler will also check whether the TaskCreationOptions value for the Task includes the PreferFairness flag, which is not on by default.&amp;#160; If the flag is set, even if the thread does have its own local queue, the scheduler will still enqueue the Task to the global queue rather than to the local queue.&amp;#160; In this manner, that Task will be considered fairly along with all other work items queued globally.&lt;/p&gt;  &lt;p&gt;What was just described is the current implementation of the PreferFairness flag in the default scheduler.&amp;#160; The implementation could of course change, but what won’t change is the purpose of the flag: by specifying PreferFairness, you’re telling the system that this Task shouldn’t be prioritized just because it’s coming from a local queue.&amp;#160; You’re telling the system that you want the system to do its best to ensure that this Task is prioritized in a first-come, first-serve nature.&lt;/p&gt;  &lt;p&gt;One other thing to note is that Task itself knows nothing of this flag; it’s just a flag set as an option on the Task.&amp;#160; It’s the scheduler that decides how it wants to handle this particular option, just as with TaskCreationOptions.LongRunning.&amp;#160; The default scheduler handles it as described above, but another scheduler (such as one you write) may do with this flag whatever it wants, including ignoring it.&amp;#160; Hence the naming “Prefer” rather than something stricter like “Guarantee”.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9822857" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Task+Parallel+Library/default.aspx">Task Parallel Library</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/ThreadPool/default.aspx">ThreadPool</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Parallel+Extensions/default.aspx">Parallel Extensions</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/.NET+4.0/default.aspx">.NET 4.0</category></item><item><title>Asynchronous methods, C# iterators, and Tasks</title><link>http://blogs.msdn.com/pfxteam/archive/2009/06/30/9809774.aspx</link><pubDate>Tue, 30 Jun 2009 16:09:32 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9809774</guid><dc:creator>toub</dc:creator><slash:comments>15</slash:comments><comments>http://blogs.msdn.com/pfxteam/comments/9809774.aspx</comments><wfw:commentRss>http://blogs.msdn.com/pfxteam/commentrss.aspx?PostID=9809774</wfw:commentRss><wfw:comment>http://blogs.msdn.com/pfxteam/rsscomments.aspx?PostID=9809774</wfw:comment><description>&lt;p&gt;More and more, developers are realizing the significant scalability advantages that asynchronous programming can provide, especially as it relates to I/O. &lt;/p&gt;  &lt;p&gt;Consider an application that needs to copy data from one stream to another stream, such as is being done in the following synchronous implementation:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;static void CopyStreamToStream(Stream input, Stream output)     &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; // Buffer space for the data to be read and written      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; byte [] buffer = new byte[0x2000];      &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; // While there’s data to be read and written      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; while(true)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // Read data. If we weren’t able to read any, bail.      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // Otherwise, write it out and start over again.      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; int numRead = input.Read(buffer, 0, buffer.Length);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (numRead == 0) break;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; output.Write(buffer, 0, numRead);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;}&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;In many cases like this, such as if the Streams are FileStream instances representing files on disk, or NetworkStream instances representing remote data, the operations being performed require little-to-no computational power, as the majority of the time is spent waiting on the I/O subsystems and devices. If one such operation is being performed at a time, that waiting isn’t such a big deal. But in a synchronous implementation like the one above, that waiting ends up blocking a thread, rendering the thread useless to do anything else while waiting. Threads by default take up a sizeable chunk of memory as well as kernel resources. Thus, if multiple concurrent calls to CopyStreamToStream are executed, multiple threads may be wasted. Since threads consume a non-negligable amount of resources, we try to limit the number of threads in an application at any one time, such as by using a thread pool, and this synchronous style of programming I/O can lead to scalability bottlenecks, especially in server components where we desire to process as many user requests concurrently as the machine’s resources will possibly allow.&lt;/p&gt;  &lt;p&gt;One solution to this problem is through compiler support. A compiler could recognize this synchronous pattern and translate it into an asynchronous one. Such a transformation of that same snippet might look like the following (note that this is hand-generated and is not the actual output of any particular compiler, and rather is my attempt to write this out concisely while still human-understandable):&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;static void CopyStreamToStreamAsync(     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Stream input, Stream output, Action&amp;lt;Exception&amp;gt; completed)      &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; // Buffer space for the data to be read and written      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; byte[] buffer = new byte[0x2000];      &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; // The read/write loop. The parameter is the IAsyncResult of the       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; // last read operation that still need to be completed with a call       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; // to EndRead. If the parameter is null, that means a new read needs       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; // to be started.      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Action&amp;lt;IAsyncResult&amp;gt; readWriteLoop = null;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; readWriteLoop = iar =&amp;gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; try       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // Determine whether to start with a BeginRead or&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // an EndRead/BeginWrite, based on whether iar is null.      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // Then, as long as the loop continues, alternate between       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // reading and writing.      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; for (bool isRead = iar == null; ; isRead = !isRead)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; switch (isRead)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // Do BeginRead(...)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case true:      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // Start the asynchronous read      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; iar = input.BeginRead(buffer, 0, buffer.Length, readResult =&amp;gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // If the read completed synchronously, immediately       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // return from the callback, as the processing of the       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // read will be handled synchronously      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // from the same thread that called BeginRead      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (readResult.CompletedSynchronously) return;      &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // The read completed asynchronously, so we need&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // to run the processing loop,      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // starting with EndRead/BeginWrite.      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; readWriteLoop(readResult);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }, null);      &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // If the read is completing asynchronously, bail, as       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // there's nothing more to do.      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // If it completed synchronously, loop around to do       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // the EndRead/BeginWrite synchronously.      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (!iar.CompletedSynchronously) return;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; break;      &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // Do BeginWrite(...)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case false:      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // Complete the previous read. If there's no more data       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // to be read/written, bail.      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; int numRead = input.EndRead(iar);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (numRead == 0)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; completed(null);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // Now that we know how much data was read, write it       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // out asynchronously      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; iar = output.BeginWrite(buffer, 0, numRead, writeResult =&amp;gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // If the write completed synchronously, allow       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // the thread that called BeginWrite      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // to handle it.      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (writeResult.CompletedSynchronously) return;      &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // Otherwise, complete the asynchronous write       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // and launch the read/write loop      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // to continue all over again.      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; output.EndWrite(writeResult);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; readWriteLoop(null);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }, null);      &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // If the write is completing asynchronously, bail,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // as there's nothing more to do.      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // Otherwise, complete the write synchronously and       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // loop around.      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (!iar.CompletedSynchronously) return;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; output.EndWrite(iar);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; break;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } catch(Exception e) { completed(e); }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; };      &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; // Start the whole process off with a read.      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; readWriteLoop(null);      &lt;br /&gt;}&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;a href="http://msdn.microsoft.com/en-us/devlabs/dd795202.aspx"&gt;The Axum compiler, available on DevLabs&lt;/a&gt;, is actually capable of these kinds of transformations for asynchronous programming, and you could imagine such functionality being baked into a mainstream language like C#. Here’s how the code could be written asynchronously with Axum:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;static asynchronous void CopyStreamToStream(Stream input, Stream output)     &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; byte [] buffer = new byte[0x2000];      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; while(true)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; int numRead = input.Read(buffer, 0, buffer.Length);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (numRead == 0) break;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; output.Write(buffer, 0, numRead);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;}&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;That’s quite lovely. Comparatively, the hand-written code is mind-numbing, and it’s not something you want to have to write each and every time you need to perform some kind of repeating operation like this asynchronously.&lt;/p&gt;  &lt;p&gt;As such, some developers have started to take advantage of C# iterators for writing asynchronous code. While not originally designed for this purpose, the compiler transformations employed for C# iterators are similar to what’s necessary for writing asynchronous code, and thus with a bit of library-based support, it’s possible to write an iterator that looks sequential but that takes advantage of asynchrony. Several libraries have been based on this approach, including the Concurrency &amp;amp; Coordination Runtime (CCR) from Microsoft Robotics, Jeffrey Richter’s AsyncEnumerator, and others.&lt;/p&gt;  &lt;p&gt;The key to taking advantage of this pattern is yielding something from an iterator that can invoke a callback when an operation completes. The pattern then becomes:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;IEnumerable&amp;lt;ThingThatHasCallbackWhenCompletes&amp;gt; AsyncMethod()     &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ...      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; yield return SomethingThatReturnsThingThatHasCallbackWhenCompletes();      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ... // code here executes when the&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // yielded ThingThatHasCallbackWhenCompletes completes      &lt;br /&gt;}&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The idea is that the iterator method returns an IEnumerable of instances that represent a piece of an asynchronous operation. A utility function is used to invoke the iterator method, and iterates over the resulting enumerator. Each time the utility function gets the next instance from the enumerator, it registers some code to monitor the operation for completion, and when the operation completes, it moves next on the enumerator. Moving next on the enumerator results in re-entering the iterator method at the code location after the last yield point, thus allowing another asynchronous operation to be yielded. In this fashion, the iterator method can in effect yield asynchronous operations, and by using “yield return” to instrument the code with those async points, you as the developer can write an asynchronous method in a manner that looks largely sequential.&lt;/p&gt;  &lt;p&gt;Now, think about the description above for the kind of object that needs to be yielded: “something that can invoke a callback when an operation completes.” Sound familiar? The System.Threading.Tasks.Task class in .NET 4 provides this exact functionality. A Task represents an asynchronous operation, and it has a ContinueWith method that enables a callback to be invoked when that asynchronous operation completes. Thus, we should be able to yield Task instances from an iterator in order to write an asynchronous method. Here’s the same CopyStreamToStream example implemented asynchronously in this fashion:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;static IEnumerable&amp;lt;Task&amp;gt; CopyStreamToStreamAsync(     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Stream input, Stream output)      &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; // Buffer space for the data to be read and written      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; byte [] buffer = new byte[0x2000];      &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; // While there’s data to be read and written      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; while(true)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // Read data asynchronously. When the operation completes,      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // if no data could be read, we’re done.      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; var read = Task&amp;lt;int&amp;gt;.Factory.FromAsync(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; input.BeginRead, input.EndRead, buffer, 0, buffer.Length, null,      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; TaskCreationOptions.DetachedFromParent);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; yield return read;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (read.Result == 0) break;      &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // Write the data asynchronously      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; yield return Task.Factory.FromAsync(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; output.BeginWrite, output.EndWrite, buffer, 0, read.Result, null,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; TaskCreationOptions.DetachedFromParent);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;}&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Much simpler. Where we were previously doing synchronous reads and writes, now we’re yielding the result of calling the built-in Task.Factory.FromAsync method, which creates Tasks that represent asynchronous reads and writes following the APM pattern. We could of course simplify this code further by using a few helper extension methods to hide some of the asynchronous details (these helpers are part of the Beta 1 samples at &lt;a title="http://code.msdn.microsoft.com/ParExtSamples" href="http://code.msdn.microsoft.com/ParExtSamples"&gt;http://code.msdn.microsoft.com/ParExtSamples&lt;/a&gt;):&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;public static Task&amp;lt;int&amp;gt; ReadTask(this Stream stream,      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; byte [] buffer, int offset, int count)      &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return Task&amp;lt;int&amp;gt;.Factory.FromAsync(stream.BeginRead, stream.EndRead,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; buffer, offset, count, null, TaskCreationOptions.DetachedFromParent);      &lt;br /&gt;}      &lt;br /&gt;      &lt;br /&gt;public static Task WriteTask(this Stream stream,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; byte [] buffer, int offset, int count)      &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return Task.Factory.FromAsync(stream.BeginWrite, stream.EndWrite,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; buffer, offset, count, null, TaskCreationOptions.DetachedFromParent);      &lt;br /&gt;}&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This then enables the previous code to be simplified to:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;static IEnumerable&amp;lt;Task&amp;gt; CopyStreamToStreamAsync(     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Stream input, Stream output)      &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; byte [] buffer = new byte[0x2000];      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; while(true)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; var read = input.ReadTask(buffer, 0, buffer.Length);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; yield return read;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (read.Result == 0) break;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; yield return output.WriteTask(buffer, 0, read.Result);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;}&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;That looks a lot like the synchronous version, and is *much* easier and less error-prone to write than the manual version shown earlier.&lt;/p&gt;  &lt;p&gt;Of course, now we need a mechanism for iterating over the asynchronous iterator. As mentioned, we can take advantage of ContinueWith for the main body of the operation (as with the earlier helpers, the following method and several variants of it are available in the &lt;a href="http://code.msdn.microsoft.com/ParExtSamples"&gt;Beta 1 samples&lt;/a&gt;):&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;public static Task Iterate(this TaskFactory factory,      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; IEnumerable&amp;lt;Task&amp;gt; asyncIterator)      &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; // Validate parameters      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if (factory == null) throw new ArgumentNullException(&amp;quot;factory&amp;quot;);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if (asyncIterator == null)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; throw new ArgumentNullException(&amp;quot;asyncIterator&amp;quot;);      &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; // Get the scheduler to use, either the one provided by the factory      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; // or the current one if the factory didn’t have one specified.      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; var scheduler = factory.TaskScheduler ?? TaskScheduler.Current;      &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; // Get an enumerator from the enumerable      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; var enumerator = asyncIterator.GetEnumerator();      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if (enumerator == null) throw new InvalidOperationException();      &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; // Create the task to be returned to the caller. And ensure      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; // that when everything is done, the enumerator is cleaned up.      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; var trs = new TaskCompletionSource&amp;lt;object&amp;gt;(factory.CreationOptions);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; trs.Task.ContinueWith(_ =&amp;gt; enumerator.Dispose(),       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; TaskContinuationOptions.DetachedFromParent, scheduler);      &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; // This will be called every time more work can be done.      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Action&amp;lt;Task&amp;gt; recursiveBody = null;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; recursiveBody = antecedent =&amp;gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; try      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // If the previous task completed with any exceptions, bail      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (antecedent != null &amp;amp;&amp;amp; antecedent.IsFaulted)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; trs.TrySetException(antecedent.Exception);      &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // If the user requested cancellation, bail.      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; else if (trs.Task.IsCancellationRequested) trs.TrySetCanceled();      &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // If we should continue iterating and there's more to iterate      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // over, create a continuation to continue processing. We only      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // want to continue processing once the current Task (as yielded      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // from the enumerator) is complete.      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; else if (enumerator.MoveNext())      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; enumerator.Current.ContinueWith(recursiveBody,      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; TaskContinuationOptions.DetachedFromParent, scheduler).      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; IgnoreExceptions();      &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // Otherwise, we're done!      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; else trs.TrySetResult(null);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // If MoveNext throws an exception, propagate that to the user      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; catch (Exception exc) { trs.TrySetException(exc); }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; };      &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; // Get things started by launching the first task      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; factory.StartNew(() =&amp;gt; recursiveBody(null),       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; TaskCreationOptions.DetachedFromParent, scheduler).      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; IgnoreExceptions();      &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; // Return the representative task to the user      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return trs.Task;      &lt;br /&gt;}&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Using this implementation, we can now run “asynchronous methods” that return IEnumerable&amp;lt;Task&amp;gt;, as did our CopyStreamToStreamAsync method:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;var asyncOperation = Task.Factory.Iterate(     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; CopyStreamToStreamAsync(input, output));&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Note that the Iterate implementation shown includes a few handy additions on top of the previous hand-coded solution. First, the Iterate method returns a Task, which can be used to track the entire asynchronous operation. Second, it supports cancellation, meaning a caller can request that the asynchronous iteration to shutdown early, even if it hasn’t completed yet. Third, we’ve now separated out the run logic into a separate method, which means that we no longer need all of that goop in the actual target asynchronous method.&lt;/p&gt;  &lt;p&gt;On top of all that, this implementation is now based on TaskFactory, which means we can do things like ensure that the code runs on a certain scheduler, such as a scheduler that targets the UI. As an example of where that is handy, consider a method that asynchronously reads from a long, remote stream and stores the resulting data into a TextBox as it’s available:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;static IEnumerable&amp;lt;Task&amp;gt; ReadStreamIntoTextBox(Stream stream)     &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; byte [] buffer = new byte[0x2000];      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Encoding enc = new UTF8Encoder();      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; while(true)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; var read = stream.ReadTask(buffer, 0, buffer.Length);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; yield return read;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (read.Result == 0) break;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; myTextBox.Text += enc.GetString(buffer, 0, read.Result)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;}&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;As previously shown, I could invoke this method as follows:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;public void button1_Click(object sender, EventArgs e)     &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Task.Factory.Iterate(ReadStreamIntoTextBox(inputStream)); // buggy      &lt;br /&gt;}&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;However, accessing myTextBox.Text from a thread other than the thread that created myTextBox is a no-no, and yet that’s potentially what will happen in the above. To address that, I want to ensure that the actual code from the iterator is executed on the UI thread (but I still don’t want the asynchronous operations to block the UI thread). To accomplish that, I can create a TaskFactory that will run tasks on the UI thread, as I do in the following code:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;public void button1_Click(object sender, EventArgs e)     &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; var uiFactory = new TaskFactory(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; TaskScheduler.FromCurrentSynchronizationContext());      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; uiFactory.Iterate(ReadStreamIntoTextBox(inputStream));      &lt;br /&gt;}&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Of course, while just being able to yield individual operations is useful, things get more interesting when you start considering multi-task continuations, as exposed through ContinueWhenAny and ContinueWhenAll. For example, in our previous copy stream example, we’re reading, then writing, then reading, then writing, and so forth. But we should be able to write the previously read bits while reading the next chunk, thereby achieving better speeds by overlapping latencies. Writing the code to do that using manual asynchrony would be a nightmare… with iterators and tasks, it’s manageable, almost fun:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;static IEnumerable&amp;lt;Task&amp;gt; CopyStreamToStreamAsync(     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Stream input, Stream output)      &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; byte[][] buffers = new byte[2][] {&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; new byte[BUFFER_SIZE], new byte[BUFFER_SIZE] };      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; int filledBufferNum = 0;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Task writeTask = null;      &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; while (true)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; var readTask = input.ReadTask(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; buffers[filledBufferNum], 0, buffers[filledBufferNum].Length);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; yield return writeTask == null ?      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; readTask :      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Task.Factory.ContinueWhenAll(new[] { readTask, writeTask },       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; tasks =&amp;gt; Task.WaitAll(tasks), // to propagate exceptions       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; TaskContinuationOptions.DetachedFromParent);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (readTask.Result == 0) break;      &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; writeTask = output.WriteTask(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; buffers[filledBufferNum], 0, readTask.Result);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; filledBufferNum = filledBufferNum == 0 ? 1 : 0;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;}&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Here, ContinueWhenAll is used to ensure that the iterator isn’t re-entered until both any pending writes and reads have completed.&lt;/p&gt;  &lt;p&gt;There are of course many variations to this code that you could implement. At the end of the day, I find it quite interesting to see how the Task primitive can be used to enable such scenarios.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9809774" 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></item><item><title>Parallel For Loops over Non-Integral Types</title><link>http://blogs.msdn.com/pfxteam/archive/2009/06/24/9802037.aspx</link><pubDate>Wed, 24 Jun 2009 20:26:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9802037</guid><dc:creator>toub</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/pfxteam/comments/9802037.aspx</comments><wfw:commentRss>http://blogs.msdn.com/pfxteam/commentrss.aspx?PostID=9802037</wfw:commentRss><wfw:comment>http://blogs.msdn.com/pfxteam/rsscomments.aspx?PostID=9802037</wfw:comment><description>&lt;P&gt;In a previous post, it was demonstrated how for &lt;A href="http://blogs.msdn.com/pfxteam/archive/2009/06/06/9703059.aspx" mce_href="http://blogs.msdn.com/pfxteam/archive/2009/06/06/9703059.aspx"&gt;loops with very small loop bodies could be parallelized&lt;/A&gt; by creating an iterator over ranges, and then using Parallel.ForEach over those ranges.&amp;nbsp; A similar technique can be used to write parallel loops over iteration spaces of non-integers.&amp;nbsp; For example, let’s say I wanted to parallelize the following loop, where the iteration range is based on doubles:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;for(double d = 0.0; d &amp;lt; 1.0; d += .001) &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Process(d); &lt;BR&gt;}&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Parallel.For only contains overloads for where the iteration variable is an Int32 or an Int64.&amp;nbsp; To accomodate doubles, one approach would be to translate the range into an integer-based range in order to use Parallel.For, and then within the body of the loop translate it into a double.&amp;nbsp; As an example, the previously shown loop could be rewritten as:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;Parallel.For(0, 1000, i =&amp;gt; &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; double d = i / 1000.0; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Process(d); &lt;BR&gt;});&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Due to floating point arithmetic, this may not be exactly the same, but it may be close enough.&amp;nbsp; Another approach is to implement an iterator like the following:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;private static IEnumerable&amp;lt;double&amp;gt; Iterate( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; double fromInclusive, double toExclusive, double step) &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for(double d = fromInclusive; d &amp;lt; toExclusive; d += step) yield return d; &lt;BR&gt;}&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;With that Iterate method, now I can parallelize the sequential loop using Parallel.ForEach:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;Parallel.ForEach(Iterate(0.0, 1.0, .001), d =&amp;gt; &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Process(d); &lt;BR&gt;});&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;This same technique can be applied to a wide variety of scenarios.&amp;nbsp; Keep in mind, however, that the IEnumerator&amp;lt;T&amp;gt; interface isn’t thread-safe, which means that Parallel.ForEach needs to take locks when accessing the data source. While ForEach internally uses some smarts to try to ammortize the cost of such locks over the processing, this is still overhead that needs to be overcome by more work in the body of the ForEach in order for good speedups to be achieved.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;Parallel.ForEach has optimizations used when working on indexible data sources, such as lists and arrays, and in those cases the need for locking is decreased.&amp;nbsp; Thus, performance may actually be improved in some cases by transforming the iteration space into a list or an array, which can be done using LINQ, even though there is both time and memory cost associated with creating an array from an enumerable. For example:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;Parallel.ForEach(Iterate(0.0, 1.0, .001).ToArray(), d =&amp;gt; &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Process(d); &lt;BR&gt;});&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Happy coding.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9802037" 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></item><item><title>Cancellation in Parallel Extensions</title><link>http://blogs.msdn.com/pfxteam/archive/2009/06/22/9791840.aspx</link><pubDate>Mon, 22 Jun 2009 09:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9791840</guid><dc:creator>mikelid</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/pfxteam/comments/9791840.aspx</comments><wfw:commentRss>http://blogs.msdn.com/pfxteam/commentrss.aspx?PostID=9791840</wfw:commentRss><wfw:comment>http://blogs.msdn.com/pfxteam/rsscomments.aspx?PostID=9791840</wfw:comment><description>&lt;P&gt;One of the great features that crosses all of Parallel Extensions types is a consistent approach to cancellation (see &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;http://blogs.msdn.com/pfxteam/archive/2009/05/22/9635790.aspx&lt;/A&gt;). In this post we explore some of the ways cancellation is used in Parallel Extensions and explain the guidance we developed. &lt;/P&gt;
&lt;P&gt;The new cancellation system is a cooperative approach based on two new types: CancellationTokenSource, which initiates cancellation requests, and CancellationToken which communicates a cancellation request to asynchronous operations and to long-running and blocking method calls.&lt;/P&gt;
&lt;P&gt;If you are experimenting with Parallel Extensions, you might like to keep an eye out for the methods that accept a CancellationToken and test them out. &lt;BR&gt;&lt;BR&gt;&lt;/P&gt;
&lt;H3&gt;Blocking calls&lt;/H3&gt;
&lt;P&gt;Some of the Parallel Extension types introduce blocking methods, for example BlockingCollection.Take() and Task.Wait(). The default overloads for these methods will block indefinitely if the condition they are waiting for never occurs. One solution used by these APIs, and many others like them, is to provide a timeout overload so that they may return after some duration and report that the condition did not occur. However, a timeout isn't particularly convenient if you only want to stop waiting if a specific activity occurs, such as a user clicking a 'cancel' button. One possibility is to wait for some amount of time such as 100 milliseconds, check if the button was pressed, and if not then go back to waiting, but this puts the burden on the call-site and must be re-implemented repeatedly; and depending on the frequency of the polling, it may also add unnecessary cost. The types in Parallel Extensions use the new cancellation system and provide overloads that accept a CancellationToken which can cause early termination of blocking methods in response to a specific cancellation request.&lt;/P&gt;
&lt;P&gt;Here are some examples of the blocking calls in Parallel Extensions that accept a CancellationToken:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;BlockingCollection: &lt;BR&gt;&lt;/STRONG&gt;void Add(T item, CancellationToken cancellationToken) &lt;BR&gt;T Take(CancellationToken cancellationToken)&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;ManualResetEventSlim: &lt;BR&gt;&lt;/STRONG&gt;void Wait(CancellationToken cancellationToken)&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;Task: &lt;BR&gt;&lt;/STRONG&gt;void Wait(CancellationToken cancellationToken) &lt;BR&gt;void WaitAll(Task[] tasks, CancellationToken cancellationToken)&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;In each case, you supply a CancellationToken to the method, and if the CancellationToken is signaled via a call to the associated CancellationTokenSource.Cancel(), then the method will wake up and throw an OperationCanceledException. This frees you from the need to use the timeouts if you are happy to wait until the condition is true or a specific cancellation request occurs. Many of these methods also have overloads that accept both a CancellationToken and a timeout, so that both needs may be accommodated. &lt;BR&gt;&lt;/P&gt;
&lt;H3&gt;Long-running calls&lt;/H3&gt;
&lt;P&gt;There are also a variety of methods that may simply take a while to complete, particularly if large amounts of data or complex processing is taking place. For example, the following call is likely to take some time, even if individual calls to DoFunc(x) are relatively fast:&lt;/P&gt;
&lt;P&gt;Parallel.For(1, 1000000000, (x) =&amp;gt; DoFunc(x));&lt;/P&gt;
&lt;P&gt;To assist with this, the Parallel APIs have overloads that accept a ParallelOptions class instance that holds a CancellationToken. The machinery inside Parallel.For(...)observes the supplied CancellationToken and will exit early if it sees that the token has be signaled (for more information on exiting loops early, see &lt;A href="http://blogs.msdn.com/pfxteam/archive/2009/05/27/9645023.aspx" mce_href="http://blogs.msdn.com/pfxteam/archive/2009/05/27/9645023.aspx"&gt;http://blogs.msdn.com/pfxteam/archive/2009/05/27/9645023.aspx&lt;/A&gt;). For example, &lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT size=2 face="Courier New"&gt;CancellationTokenSource cts = new CancellationTokenSource(); &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;ParallelOptions options = new ParallelOptions &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&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; {CancellationToken = cts.Token}; &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;Parallel.For(1, 100, options, (x) =&amp;gt; DoSlowFunc(x)); &lt;BR&gt;// from another thread, call cts.Cancel() to request cancellation.&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;As you can see, the approach for canceling blocking calls and long-running calls is identical. In both cases you supply a CancellationToken to a specific method call and use the associated CancellationTokenSource to signal a cancellation request. &lt;BR&gt;&lt;BR&gt;&lt;/P&gt;
&lt;H3&gt;Digression: Internal cancellation&lt;/H3&gt;
&lt;P&gt;In certain situations in Parallel Extensions and in other systems, it is necessary to wake up a blocked method for reasons that aren't due to explicit cancellation by a user. For example, if one thread is blocked on blockingCollection.Take() due to the collection being empty and another thread subsequently calls blockingCollection.CompleteAdding(), then the first call should wake up and throw an InvalidOperationException to represent an incorrect usage. A great way to implement this is to use an internal CancellationTokenSource that can wake things up due to internal concerns, and to link it to a second, external CancellationTokenSource that has been supplied by the user. For example, the following captures the essential details of how CompleteAdding() and Take(CancellationToken) are implemented:&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2 face="Courier New"&gt;class BlockingCollection&amp;lt;T&amp;gt; &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;{ &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;nbsp;&amp;nbsp; CancellationTokenSource internalCTS = new CancellationTokenSource();&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;nbsp;&amp;nbsp; public void FinishAdding() &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //... &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; internalCTS.Cancel(); &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;public T Take(CancellationToken externalToken) &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; using(CancellationTokenSource linkedTokenSource = &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CancellationTokenSource.CreateLinkedTokenSource( &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; internalCTS.Token, externalToken)){ &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return InternalTake(linkedTokenSource.Token); &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch (OperationCanceledException oce) &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(internalCTS.Token.IsCancellationRequested) &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new InvalidOperationException("..msg.."); &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else if(externalToken.IsCancellationRequested) &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new OperationCanceledException(externalToken); &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else throw; &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;} &lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;In this fragment, a linked CancellationTokenSource is created and its token passed to the InternalTake() method. This simplifies the implementation for InternalTake() but still allows it to be woken up due to either the external token being signaled or an incorrect concurrent call to CompleteAdding(). If the InternalTake() method throws an OperationCanceledException, we can test the individual tokens to determine what the cause was and take appropriate action. Note that oce.CancellationToken will be equal to linkedTokenSource.Token as this is the token that was actually being observed, but we can look at the original tokens to determine the cause for the linked token being signaled. There is a minor risk of confusion if both sources are signaled simultaneously, but this confusion is benign as it is reasonable to behave as though either source was responsible, and a particular implementation may choose to prioritize one mechanism over the other. &lt;BR&gt;&lt;/P&gt;
&lt;H3&gt;Cooperative cancellation with user-code&lt;/H3&gt;
&lt;P&gt;Both TPL and PLINQ provide infrastructure that calls back to user code. If the user code is long running or blocking, then it is very useful for the user code to be able to respond to cancellation in a cooperative fashion. TPL and PLINQ achieve this by tracking a supplied CancellationToken, and if they see some user code throw an OperationCanceledException that mentions this specific token, then it is treated as &lt;I&gt;cooperative acknowledgement of cancellation&lt;/I&gt;. This means that both TPL and PLINQ understand that the user code did not suffer some catastrophic exceptional conditional, but rather that it is simply responding to cancellation. As a result, TPL and PLINQ constructs will simply exit with an OperationCanceledException of their own, rather than aggregating exceptions from all the participating worker threads and throwing an AggregateException.&lt;/P&gt;
&lt;P&gt;PLINQ follows this basic plan; for example, the following query will throw a single OperationCanceledException if the CancellationTokenSource becomes signaled. It doesn't matter whether PLINQ or the user delegate sees the cancellation request first, as the user-delegate exception will be correctly understood by the PLINQ execution engine.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT size=2 face="Courier New"&gt;CancellationTokenSource cts = new CancellationTokenSource(); &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;var resultArray = &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;data.AsParallel() &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .WithCancellation(cts.Token) &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Select((x) =&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&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="Courier New"&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; if (cts.Token.IsCancellationRequested) &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&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; throw new OperationCanceledException(cts.Token); &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ... &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .ToArray();&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;In both PLINQ and TPL, it is interesting to note that the external cancellation token is not supplied back to the user-delegate via a parameter as may be expected. This would have bloated the number of method overloads considerably and, as shown above, the external token can be conveniently accessed via closures or equivalent techniques.&lt;/P&gt;
&lt;P&gt;If the user code throws an OperationCanceledException but one or more "normal" exceptions occur on other threads, then all of the exceptions will be collated into an AggregateException, including the OperationCanceledException. Hence, if only cancellation occurred then a single OperationCanceledException is thrown, but an actual failure will always result in an AggregateException. &lt;BR&gt;&lt;BR&gt;&lt;/P&gt;
&lt;H3&gt;PLINQ Queries&lt;/H3&gt;
&lt;P&gt;PLINQ offers deep support for cancellation and endeavors to ensure that cancellation will be enacted swiftly for any query. For queries that involve only simple and fast user delegates, simply supply a CancellationToken via the WithCancellation() method and PLINQ takes care of the rest. &lt;A&gt;&lt;FONT color=#000000&gt;If your query involves long-running or blocking user code, then you should use the cooperative cancellation pattern described in the preceding section&lt;/FONT&gt;&lt;/A&gt;. For reasons that are discussed in the next section, PLINQ may not check for cancellation every time it calls a user-delegate, and so long running delegates should check cancellation frequently (&lt;A&gt;&lt;FONT color=#000000&gt;as a working rule of thumb, PLINQ will check for cancellation approximately once per one hundred calls to a user delegate&lt;/FONT&gt;&lt;/A&gt;). For example, if a delegate call runs for 50ms but does not perform any cancellation checks of its own, then PLINQ may not detect the cancellation request itself for up to 5 seconds, and this could significantly affect a user’s experience. For this reason, we recommend that long-running delegates called from PLINQ queries should check for cancellation as frequently as possible. A good lower bound is to check cancellation once per few thousand IL instructions executed, and an upper bound is to check no less frequently than once per 10ms, but once per 1ms is preferred to ensure snappy response.&lt;/P&gt;
&lt;P&gt;The following example demonstrates a user delegate that may run for a while, and so checks cancellation itself every few thousand IL instructions. This provides for timely cancellation support with a negligible cost to performance.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT size=2 face="Courier New"&gt;// Assume an external CancellationToken 'token' has been supplied. &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;int[] data = ...; &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;var query = &lt;BR&gt;&amp;nbsp;&amp;nbsp; data.AsParallel() &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .WithCancellation(token) &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Select((x) =&amp;gt; &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;nbsp;&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="Courier New"&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; int result = 0; &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&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; for ( int i = 0; i &amp;lt; x; i++ ) { &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&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; for (int j = 0; j &amp;lt; 1000 * x; j++) &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&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; result += SimpleFunc(i,j); &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&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; token.ThrowIfCancellationRequested(); &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&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; return result;}) &lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2 face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .ToArray();&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;[Update: the call to token.ThrowIfCancellationRequested shown above is not available in Beta1 (but will appear in subsequent releases).&amp;nbsp; This behavior can be acheived via a manual test-and-throw as shown in earlier examples, or via the extension-method approach described in the comments.&amp;nbsp; -Mike]&lt;/P&gt;
&lt;H3&gt;Summary&lt;/H3&gt;
&lt;P&gt;The Parallel Extension types use the new cancellation system to provide consistent and rich cancellation features. All of the long-running and blocking methods in Parallel Extensions provide overloads that take a CancellationToken, and any callbacks made to user-code can participate in the process. Application code can also make use of the same ideas and facilities to ensure that cancellation can be a fully supported feature in any situation.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9791840" 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/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/Cancellation/default.aspx">Cancellation</category></item><item><title>Tasks and the Event-based Asynchronous Pattern</title><link>http://blogs.msdn.com/pfxteam/archive/2009/06/19/9791857.aspx</link><pubDate>Fri, 19 Jun 2009 18:43:10 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9791857</guid><dc:creator>toub</dc:creator><slash:comments>10</slash:comments><comments>http://blogs.msdn.com/pfxteam/comments/9791857.aspx</comments><wfw:commentRss>http://blogs.msdn.com/pfxteam/commentrss.aspx?PostID=9791857</wfw:commentRss><wfw:comment>http://blogs.msdn.com/pfxteam/rsscomments.aspx?PostID=9791857</wfw:comment><description>&lt;p&gt;As has been discussed previously, one of the new features in the Task Parallel Library is &lt;a href="http://blogs.msdn.com/pfxteam/archive/2009/06/02/9685804.aspx"&gt;TaskCompletionSource&amp;lt;TResult&amp;gt;&lt;/a&gt;, which enables the creation of a Task&amp;lt;TResult&amp;gt; that represents any other asynchronous operation.&amp;#160; &lt;/p&gt;  &lt;p&gt;There are a wide variety of sources in the .NET Framework for asynchronous work.&amp;#160; One comes from components that implement the Asynchronous Programming Model (APM) pattern, which we discussed &lt;a href="http://blogs.msdn.com/pfxteam/archive/2009/06/09/9716439.aspx"&gt;here&lt;/a&gt;.&amp;#160; Another includes types that implement the Event-based Asynchronous Pattern (EAP).&amp;#160; For some synchronous method Xyz, the EAP provides an asynchronous counterpart XyzAsync.&amp;#160; Calling this method launches the asynchronous work, and when the work completes, a corresponding XyzCompleted event is raised. (That’s an oversimplification of the pattern, but it provides a grounding.)&lt;/p&gt;  &lt;p&gt;For many situations, the EAP is quite straightforward and simple to use.&amp;#160; However, there are cases where you’d like to be able to do things like join across multiple EAP asynchronous invocations, such as to download three different web pages asynchronously, and only when all three have completed do something else.&amp;#160; Tasks in .NET 4.0 make this kind of operation easy, through Task.Factory.ContinueWhenAll (or ContinueWhenAny if you want to do something when any one of the items completes rather than when all of them do).&amp;#160; However, in order to use these methods, you need Tasks, thus to use them with components that implement the EAP, you need to create Tasks from EAP.&amp;#160; TaskCompletionSource&amp;lt;TResult&amp;gt; can be used to do exactly that. &lt;/p&gt;  &lt;p&gt;First, let’s create two small helper functions that we can reuse over and over for multiple EAP-to-Task implementations: &lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;private static TaskCompletionSource&amp;lt;T&amp;gt; CreateSource&amp;lt;T&amp;gt;(object state)      &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return new TaskCompletionSource&amp;lt;T&amp;gt;(       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; state, TaskCreationOptions.DetachedFromParent);       &lt;br /&gt;} &lt;/p&gt;    &lt;p&gt;private static void TransferCompletion&amp;lt;T&amp;gt;(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; TaskCompletionSource&amp;lt;T&amp;gt; tcs, AsyncCompletedEventArgs e,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Func&amp;lt;T&amp;gt; getResult)       &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if (e.UserState == tcs)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (e.Cancelled) tcs.TrySetCanceled();       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; else if (e.Error != null) tcs.TrySetException(e.Error);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; else tcs.TrySetResult(getResult());       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;}&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The first helper, CreateSource, simply creates an instance of TaskCompletionSource&amp;lt;T&amp;gt; with the right type and settings.&amp;#160; I’ve included TaskCreationOptions.DetachedFromParent under the assumption that tasks created for the EAP pattern aren’t necessarily meant to participate in parent/child relationships, but you could certainly change this if your scenarios needed that functionality. &lt;/p&gt;  &lt;p&gt;The second helper, TransferCompletion, will be used whenever an EAP event signals completion of an asynchronous operation.&amp;#160; It takes the AsyncCompletedEventArgs provided through the XyzCompleted event and uses it to determine whether the operation completed due to cancellation or due to an unhandled exception.&amp;#160; Both of those pieces of data are standard to the base AsyncCompletedEventArgs class. However, each EAP operation typically comes with its own type derived from AsyncCompletedEventArgs: to be able to use this one helper function with any of those to mine the result of the operation, TransferCompletion also accepts a Func&amp;lt;T&amp;gt; that will return the results from the derived instance.&amp;#160; &lt;/p&gt;  &lt;p&gt;With those two helpers, writing a Task wrapper for an EAP operation is a cinch.&amp;#160; Consider System.Net.WebClient, which provides support for downloading and uploading to and from URIs, with methods like DownloadData.&amp;#160; We can write a Task-based wrapper for DownloadData in just a few lines (in this case, as an extension method): &lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;public static Task&amp;lt;byte[]&amp;gt; DownloadDataTask(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; this WebClient webClient, Uri address)       &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; var tcs = CreateSource&amp;lt;byte[]&amp;gt;(address);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; webClient.DownloadDataCompleted +=       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (sender, e) =&amp;gt; TransferCompletion(tcs, e, () =&amp;gt; e.Result);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; webClient.DownloadDataAsync(address, tcs);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return tcs.Task;       &lt;br /&gt;}&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;We first create a TaskCompletionSource&amp;lt;byte[]&amp;gt; whose Task&amp;lt;byte[]&amp;gt; will be returned from the method.&amp;#160; We then register with the DownloadDataCompleted event handler, such that when the event is raised, the downloaded data (or exception or cancellation information) will be transferred to the returned Task.&amp;#160; And then we start the operation.&amp;#160; Piece of cake. &lt;/p&gt;  &lt;p&gt;One interesting thing to note about the EAP is that some implementations support multiple asynchronous operations concurrently on the same instance.&amp;#160; In such cases, a user-supplied token is needed to correlate the asynchronous invocations to the asynchronous completions (something that’s provided in Task implicitly by having a Task reference returned from and serving as a reference for an asynchronous operation).&amp;#160; For that purpose, we pass the created TaskCompletionSource&amp;lt;TResult&amp;gt; as the user-supplied token, and in TransferCompletion, we only transfer the results if the token received matches the target completion source.&amp;#160; If it doesn’t match, this is an event completion for another operation and should be ignored. &lt;/p&gt;  &lt;p&gt;One potential issue with the previously shown implementation (and with the EAP pattern in general) is that, if they’re used over and over, the XyzCompleted event handlers will start to build up.&amp;#160; Delegates are being registered with the event but not released.&amp;#160; To fix that, we can also remove the event handler in the delegate handling the event.&amp;#160; For example, DownloadDataTask can be rewritten as: &lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;public static Task&amp;lt;byte[]&amp;gt; DownloadDataTask(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; this WebClient webClient, Uri address)       &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; var tcs = CreateSource&amp;lt;byte[]&amp;gt;(address);       &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; DownloadDataCompletedEventHandler handler = null;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; handler = (sender, e) =&amp;gt; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; TransferCompletionToTask(tcs, e, () =&amp;gt; e.Result);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; webClient.DownloadDataCompleted -= handler;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; };       &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; webClient.DownloadDataCompleted += handler;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; try { webClient.DownloadDataAsync(address, tcs); }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; catch {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; webClient.DownloadDataCompleted -= handler;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; tcs.TrySetCanceled();       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; throw;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return tcs.Task;       &lt;br /&gt;}&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The Beta 1 samples available at &lt;a title="http://code.msdn.microsoft.com/ParExtSamples" href="http://code.msdn.microsoft.com/ParExtSamples"&gt;http://code.msdn.microsoft.com/ParExtSamples&lt;/a&gt; already include Task-based extensions for WebClient, as well as extensions for other EAP implementations like SmtpClient and Ping.&amp;#160; Download and enjoy!&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9791857" 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></item><item><title>How PLINQ processes an IEnumerable&lt;T&gt; on multiple cores</title><link>http://blogs.msdn.com/pfxteam/archive/2009/06/13/9741072.aspx</link><pubDate>Sat, 13 Jun 2009 09:39:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9741072</guid><dc:creator>igoro</dc:creator><slash:comments>14</slash:comments><comments>http://blogs.msdn.com/pfxteam/comments/9741072.aspx</comments><wfw:commentRss>http://blogs.msdn.com/pfxteam/commentrss.aspx?PostID=9741072</wfw:commentRss><wfw:comment>http://blogs.msdn.com/pfxteam/rsscomments.aspx?PostID=9741072</wfw:comment><description>&lt;P&gt;As Ed Essey explained in &lt;A title="Partitioning in PLINQ" href="http://blogs.msdn.com/pfxteam/archive/2009/05/28/9648672.aspx" mce_href="http://blogs.msdn.com/pfxteam/archive/2009/05/28/9648672.aspx"&gt;Partitioning in PLINQ&lt;/A&gt;, partitioning is an important step in PLINQ execution. Partitioning splits up a single input sequence into multiple sequences that can be processed in parallel. This post further explains chunk partitioning, the most general partitioning scheme that works on any IEnumerable&amp;lt;T&amp;gt;.&lt;/P&gt;
&lt;P&gt;Chunk partitioning appears in two places in Parallel Extensions. First, it is one of the algorithms that PLINQ uses under the hood to execute queries in parallel. Second, chunk partitioning is available as a standalone algorithm through the Partitioner.Create() method.&lt;/P&gt;
&lt;P&gt;To explain the design of the chunk partitioning algorithm, let's walk through the possible ways of processing an IEnumerable&amp;lt;T&amp;gt; with multiple worker threads, finally arriving at the solution used in PLINQ (approach 4).&lt;/P&gt;
&lt;P&gt;&lt;BR&gt;&lt;STRONG&gt;Approach 1: Load the input sequence into an intermediate array&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;As a simple solution, we could walk over the input sequence and store all elements into an array. Then, we can split up the array into ranges, and assign each range to a different worker.&lt;/P&gt;
&lt;P&gt;The disadvantage of this approach is that we need to allocate an array large enough to store all input elements. If the input sequence is long, this will algorithm leads to unnecessarily large memory consumption. Also, we need to wait until the entire input sequence is ready before the workers can start executing.&lt;/P&gt;
&lt;P&gt;&lt;BR&gt;&lt;STRONG&gt;Approach 2: Hand out elements to threads on demand&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;An entirely different approach is to have all worker threads share one input enumerator. When a worker is ready to process the next input element, it takes a shared lock, gets the next element from the input enumerator, and releases the lock.&lt;/P&gt;
&lt;P&gt;This algorithm has a fairly large overhead because processing every element requires locking. Also, handing out elements individually is prone to poor cache behavior.&lt;/P&gt;
&lt;P&gt;This approach does have an interesting advantage over Approach 1, though: since workers receive data on demand, the workers that finish faster will come back to request more work. In contrast, Approach 1 splits up all work ahead of time, and a worker that is done early simply goes away.&lt;/P&gt;
&lt;P&gt;&lt;BR&gt;&lt;STRONG&gt;Approach 3: Hand out elements in chunks&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;To mitigate the two drawbacks of Approach 2 (synchronization cost and cache behavior), we can hand out elements to threads in "chunks". When a thread is ready to process more inputs, it will take say 64 elements from the input enumerator.&lt;/P&gt;
&lt;P&gt;Unfortunately, while this approach nicely amortizes the synchronization cost over multiple elements, it does not work well for short inputs. For example, if the input contains 50 elements and the chunk size is 64, all inputs will go into a single partition. Even if the work per element is large, we will not be able to benefit from parallelism, since one worker gets all the work.&lt;/P&gt;
&lt;P&gt;And since IEnumerable&amp;lt;T&amp;gt; in general does not declare its length, we cannot simply tune the chunk size based on the input sequence length.&lt;/P&gt;
&lt;P&gt;&lt;BR&gt;&lt;STRONG&gt;Approach 4: Hand out elements in chunks of increasing size&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;A solution to the problem with small inputs is to use chunks of a growing size. The first chunk assigned to each thread is of size 1 and subsequent chunks are gradually larger, until a specific threshold is reached.&lt;/P&gt;
&lt;P&gt;Our solution doubles the chunk size every few chunks. So, each thread first receives a few chunks of size 1, then a few chunks of size 2, then 4, and so forth. Once the chunk size reaches a certain threshold, it remains constant.&lt;/P&gt;
&lt;P&gt;This chunking strategy ensures that if the input is short, it will still get split up fairly among the cores. But, the chunk size also grows fairly quickly, and the per-chunk overheads are small for large inputs. Also, the algorithm is quite good at load-balancing, so if one worker is taking longer to process its inputs, other workers will process more elements to decrease the overall processing time.&lt;/P&gt;
&lt;P&gt;One interesting consequence of the chunk partitioning algorithm is that multiple threads will call MoveNext() on the input enumerator. The worker threads will use a lock to ensure mutual exclusion, but the enumerator must not assume that MoveNext() will be called from a particular thread (e.g., it should not use thread-local storage, manipulate UI, etc).&lt;/P&gt;
&lt;P&gt;The current implementation of both PLINQ chunk partitioning and Partitioner.Create() follows approach 4 fairly closely. Now you know&amp;nbsp;how it behaves&amp;nbsp;and why!&lt;BR&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9741072" 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/.NET+4.0/default.aspx">.NET 4.0</category></item><item><title>Achieving Speedups with Small Parallel Loop Bodies</title><link>http://blogs.msdn.com/pfxteam/archive/2009/06/06/9703059.aspx</link><pubDate>Sat, 06 Jun 2009 20:27:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9703059</guid><dc:creator>toub</dc:creator><slash:comments>14</slash:comments><comments>http://blogs.msdn.com/pfxteam/comments/9703059.aspx</comments><wfw:commentRss>http://blogs.msdn.com/pfxteam/commentrss.aspx?PostID=9703059</wfw:commentRss><wfw:comment>http://blogs.msdn.com/pfxteam/rsscomments.aspx?PostID=9703059</wfw:comment><description>&lt;P&gt;The Parallel class represents a significant advancement in parallelizing managed loops.&amp;nbsp; For many common scenarios, it just works, resulting in terrific speedups.&amp;nbsp; However, while ideally Parallel.For could be all things to all people, such things rarely work out, and we’ve had to prioritize certain scenarios over others.&lt;/P&gt;
&lt;P&gt;One area Parallel.For may fall a bit short is in attempts to use it with very small loop bodies, such as:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;int [] array = new int[100000000]; &lt;BR&gt;Parallel.For(0, array.Length, i=&amp;gt; &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; array[i] = i*i*i; &lt;BR&gt;});&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Such an operation should be readily parallelizable; after all, every iteration is completely independent of every other iteration, and we’re dealing with a big data parallel problem.&amp;nbsp; The devil is in the details, however.&amp;nbsp; To handle typical scenarios where the time it takes to complete each iteration ends up being non-uniform, Parallel.For’s implementation takes a lot of care to load balance across all threads participating in the loop, and that load balancing comes at a small performance cost.&amp;nbsp; This cost is typically trumped by the performance benefits that come from doing the load balancing; however, when the body of the loop is as tiny as it is in the example above, even small overheads add up.&amp;nbsp; Another overhead that also contributes is the delegate invocation required to invoke the loop body.&amp;nbsp; It can be easy to forget when looking at a Parallel.For call that Parallel.For is really just a method, accepting as a parameter a delegate to be invoked for every iteration.&amp;nbsp; That invocation isn’t free, and in the above case may even be more expensive than the body of the loop itself.&lt;/P&gt;
&lt;P&gt;Fear not, however, as there exist ways to still achieve good speedups on such cases.&amp;nbsp; One way is based on creating larger chunks of work for Parallel to operate on: as the chunk size increases, the overhead costs start to pale in comparison, and speedups are realized.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;Consider a new ForRange method you could implement:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;public static ParallelLoopResult ForRange( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int fromInclusive, int toExclusive, Action&amp;lt;int, int&amp;gt; body);&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Unlike For, which invokes the body once per iteration, ForRange will invoke the body with a start and end of a range.&amp;nbsp; Thus, given an initial sequential loop like the following:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;for(int i=0; i&amp;lt;N; i++) &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DoWork(i); &lt;BR&gt;}&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;with For it would be parallelized by replacing the for loop with a Parallel.For:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;Parallel.For(0, N, i=&amp;gt; &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DoWork(i); &lt;BR&gt;});&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;and with ForRange, it would be parallelized by &lt;EM&gt;wrapping&lt;/EM&gt; the for loop with a ForRange:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;ForRange(0, N, (from,to) =&amp;gt; &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for(int i=from; i&amp;lt;to; i++) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DoWork(i); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;});&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;There are several ways we can now implement ForRange.&amp;nbsp; The first is simply by doing a little math.&amp;nbsp; We can calculate the boundaries of each range and use a Parallel.For to run the user-supplied body action for each range, e.g.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;public static ParallelLoopResult ForRange( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int fromInclusive, int toExclusive, Action&amp;lt;int, int&amp;gt; body) &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int numberOfRanges = Environment.ProcessorCount; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int range = toExclusive - fromInclusive; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int stride = range / numberOfRanges; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (range &amp;lt;= 0) numberOfRanges = 0; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return Parallel.For(0, numberOfRanges, i =&amp;gt; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int start = i * stride; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int end = (i == numberOfRanges - 1) ? toExclusive : start + stride; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; body(start, end); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }); &lt;BR&gt;}&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Another way is actually by using Parallel.ForEach under the covers.&amp;nbsp; Rather than doing the math as was done above, we can write an iterator in C# that yields the ranges, and then Parallel.ForEach over those ranges, e.g.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;public static ParallelLoopResult ForRange( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int fromInclusive, int toExclusive, Action&amp;lt;int, int&amp;gt; body) &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int rangeSize = (toExclusive - fromInclusive) / Environment.ProcessorCount; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (rangeSize == 0) rangeSize = 1; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return Parallel.ForEach( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CreateRanges(fromInclusive, toExclusive, rangeSize), range =&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; body(range.Item1, range.Item2); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }); &lt;BR&gt;}&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;private static IEnumerable&amp;lt;Tuple&amp;lt;int,int&amp;gt;&amp;gt; CreateRanges( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int fromInclusive, int toExclusive, int rangeSize) &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Enumerate all of the ranges &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (int i = fromInclusive; i &amp;lt; toExclusive; i += rangeSize) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int from = i, to = i + rangeSize; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (to &amp;gt; toExclusive) to = toExclusive; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; yield return Tuple.Create(from, to); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;}&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;(You can download an implementation of ForRange as part of the Beta 1 samples at &lt;A title=http://code.msdn.microsoft.com/ParExtSamples href="http://code.msdn.microsoft.com/ParExtSamples" mce_href="http://code.msdn.microsoft.com/ParExtSamples"&gt;http://code.msdn.microsoft.com/ParExtSamples&lt;/A&gt;.)&lt;/P&gt;
&lt;P&gt;In general, we expect the design and implementation of Parallel.For will be right for the vast majority of scenarios.&amp;nbsp; However, solutions like those above can be used to accommodate cases that don’t quite fit the mold.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9703059" 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/Parallelism+Blockers/default.aspx">Parallelism Blockers</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Code+Samples/default.aspx">Code Samples</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Parallel+Extensions/default.aspx">Parallel Extensions</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/.NET+4.0/default.aspx">.NET 4.0</category></item><item><title>Mechanisms for Creating Tasks</title><link>http://blogs.msdn.com/pfxteam/archive/2009/06/03/9691796.aspx</link><pubDate>Wed, 03 Jun 2009 16:33:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9691796</guid><dc:creator>toub</dc:creator><slash:comments>16</slash:comments><comments>http://blogs.msdn.com/pfxteam/comments/9691796.aspx</comments><wfw:commentRss>http://blogs.msdn.com/pfxteam/commentrss.aspx?PostID=9691796</wfw:commentRss><wfw:comment>http://blogs.msdn.com/pfxteam/rsscomments.aspx?PostID=9691796</wfw:comment><description>&lt;P&gt;The core entity in the Task Parallel Library around which everything else revolves is System.Threading.Tasks.Task.&amp;nbsp; The most common way of creating a Task will be through the StartNew method on the TaskFactory class, a default instance of which is exposed through a static property on Task, e.g.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;var t = Task.Factory.StartNew(() =&amp;gt; &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; … // body of the task goes here &lt;BR&gt;});&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;There are, however, other ways of creating tasks.&amp;nbsp; For example, while using StartNew is the preferred mechanism to create a Task and schedule/start it, we do support separating those two operations into two discrete actions, e.g.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;var t = new Task(() =&amp;gt; &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; … // body of the task goes here &lt;BR&gt;}); &lt;BR&gt;… // the task has been created but not scheduled &lt;BR&gt;t.Start(); // now schedule it&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Moreover, StartNew isn’t alone on TaskFactory; other methods like ContinueWhenAll, ContinueWhenAny, and FromAsync may all be used to create Task instances. Task also exposes a ContinueWith mechanism that can be used to create a Task that will be scheduled when the antecedent task (the Task on which ContinueWith is being called) completes.&lt;/P&gt;
&lt;P&gt;Finally, the &lt;A href="http://blogs.msdn.com/pfxteam/archive/2009/06/02/9685804.aspx" mce_href="http://blogs.msdn.com/pfxteam/archive/2009/06/02/9685804.aspx"&gt;TaskCompletionSource&amp;lt;TResult&amp;gt;&lt;/A&gt; type can be used to create a Task&amp;lt;TResult&amp;gt; completely controlled by the completion source instance, through its SetResult, SetException, and SetCanceled methods (and their TrySet* variants).&lt;/P&gt;
&lt;P&gt;Each of these different ways of creating a Task has different behaviors associated with it.&amp;nbsp; The differences between them may not be obvious at first, but with a little thought, it should be clear why things behave the way they do.&amp;nbsp; For example, calling Start on a Task created by StartNew is invalid (i.e. results in an exception)… you can’t start an already started Task.&amp;nbsp; In contrast, a Task created by a Task’s constructor won’t have been scheduled, so it’s perfectly valid to call Start on it.&amp;nbsp; Calling Start on a Task returned by a TaskCompletionSource&amp;lt;TResult&amp;gt; makes little sense, as there’s nothing to “start”, so that’s invalid.&amp;nbsp; It’s invalid to call Start on a continuation task (e.g. one created by ContinueWith, ContinueWhenAny, or ContinueWhenAll) because the work should only be scheduled when the antecedent(s) has completed.&amp;nbsp; And it’s invalid to call Start on a task created by FromAsync, because the work being done has already been initiated through a call to the beginMethod passed to FromAsync.&lt;/P&gt;
&lt;P&gt;These kinds of behavioral differences can be quite useful when building up abstractions on top of tasks.&amp;nbsp; For example, let’s say I want to implement a factory method for creating “delayed” tasks, ones that won’t actually be scheduled until some user-supplied timeout has occurred.&amp;nbsp; One way to write this would be as follows:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;public static Task StartNewDelayed(int millisecondsDelay, Action action) &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Validate arguments &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (millisecondsDelay &amp;lt; 0) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new ArgumentOutOfRangeException("millisecondsDelay"); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (action == null) throw new ArgumentNullException("action"); &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Create the task &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var t = new Task(action); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Start a timer that will trigger it &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var timer = new Timer( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _ =&amp;gt; t.Start(), null, millisecondsDelay, Timeout.Infinite);&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; t.ContinueWith(_ =&amp;gt; timer.Dispose());&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return t; &lt;BR&gt;}&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;This implementation creates a new Task to run the provided action, but doesn’t immediately start it.&amp;nbsp; Instead, it creates a Timer with the user-supplied delay, and when the timer expires, the Timer’s callback starts the task.&amp;nbsp; Once the timer has been started, the Task is returned to the user.&lt;/P&gt;
&lt;P&gt;One problem with this implementation, which you might have guess based on earlier paragraphs, is that the Task returned to the user was created using the Task’s constructor.&amp;nbsp; This means it can be explicitly Start’d.&amp;nbsp; And that means the Task returned from StartNewDelayed could be started by the consumer prior to the Timer firing.&amp;nbsp; That’s bad for two reasons: one, it breaks expectations about the behavior of the Task and the associated delay, and two, a Task may only be started once.&amp;nbsp; If the Task is explicitly started and then the timer’s callback tries to Start the Task, kaboom: Start will throw an exception (since the Task was already started), the exception will go unhandled, and the app will come crumbling down.&lt;/P&gt;
&lt;P&gt;Given what we now know about behaviors associated with creating tasks, we can use a different mechanism for creating a task that doesn’t allow the Task to be explicitly started.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;public static Task StartNewDelayed(int millisecondsDelay, Action action) &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Validate arguments &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (millisecondsDelay &amp;lt; 0) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new ArgumentOutOfRangeException("millisecondsDelay"); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (action == null) throw new ArgumentNullException("action"); &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Create a trigger used to start the task &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var tcs = new TaskCompletionSource&amp;lt;object&amp;gt;(); &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Start a timer that will trigger it &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var timer = new Timer( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _ =&amp;gt; tcs.SetResult(null), null, millisecondsDelay, Timeout.Infinite); &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Create and return a task that will be scheduled when the trigger fires. &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return tcs.Task.ContinueWith(_ =&amp;gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; timer.Dispose();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; action();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }); &lt;BR&gt;}&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;In this new implementation, I’ve taken advantage of the fact that a continuation task can’t be explicitly started and can be used to run arbitrary user code.&amp;nbsp; The timer is used to resolve a TaskCompletionSource&amp;lt;TResult&amp;gt;, and a continuation off of that completion source is used to run the action.&amp;nbsp; It’s that continuation that’s returned.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9691796" 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></item><item><title>The Nature of TaskCompletionSource&lt;TResult&gt;</title><link>http://blogs.msdn.com/pfxteam/archive/2009/06/02/9685804.aspx</link><pubDate>Tue, 02 Jun 2009 16:09:32 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9685804</guid><dc:creator>toub</dc:creator><slash:comments>8</slash:comments><comments>http://blogs.msdn.com/pfxteam/comments/9685804.aspx</comments><wfw:commentRss>http://blogs.msdn.com/pfxteam/commentrss.aspx?PostID=9685804</wfw:commentRss><wfw:comment>http://blogs.msdn.com/pfxteam/rsscomments.aspx?PostID=9685804</wfw:comment><description>&lt;p&gt;The Task Parallel Library is centered around the &lt;a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.task(VS.100).aspx"&gt;Task&lt;/a&gt; class and its derived &lt;a href="http://msdn.microsoft.com/en-us/library/dd321424(VS.100).aspx"&gt;Task&amp;lt;TResult&amp;gt;&lt;/a&gt;. The main purpose of these types is to represent the execution of an asynchronous workload and to provide an object with a means to operate on that workload, whether it be to wait for it, to continue from it, or the like. The primary type of asynchronous workload supported by Task is the execution of a delegate, either an Action or a Func&amp;lt;T&amp;gt;, such that the delegate’s execution in the underlying scheduler is represented by the Task. But in any compositional system that wants to use Task as its centerpiece, just support for asynchronous delegate execution isn’t enough: support must be provided for other asynchronous operations as well. For example, there are a variety of asynchronous operations already implemented in the .NET Framework and exposed through the Asynchronous Programming Model (APM) pattern or the Event-Based Asynchronous Pattern (EAP). In both of these cases, we’d like to be able to refer to these asynchronous operations as Tasks and operate on them as Tasks, even though the underlying work isn’t necessarily being performed by scheduling and executing a delegate. (More to come on both of those in future posts.)&lt;/p&gt;  &lt;p&gt;To support such a paradigm with Tasks, we need a way to retain the Task façade and the ability to refer to an arbitrary asynchronous operation as a Task, but to control the lifetime of that Task according to the rules of the underlying infrastructure that’s providing the asynchrony, and to do so in a manner that doesn’t cost significantly. This is the purpose of TaskCompletionSource&amp;lt;TResult&amp;gt;.&lt;/p&gt;  &lt;p&gt;The TaskCompletionSource&amp;lt;TResult&amp;gt; type serves two related purposes, both alluded to by its name: it is a source for creating a task, and the source for that task’s completion. In essence, a TaskCompletionSource&amp;lt;TResult&amp;gt; acts as the producer for a Task&amp;lt;TResult&amp;gt; and its completion. You create a TaskCompletionSource&amp;lt;TResult&amp;gt; and hand the underlying Task&amp;lt;TResult&amp;gt; it’s created, accessible from its Task property. Unlike Tasks created by Task.Factory.StartNew, the Task handed out by TaskCompletionSource&amp;lt;TResult&amp;gt; does not have any scheduled delegate associated with it. Rather, TaskCompletionSource&amp;lt;TResult&amp;gt; provides methods that allow you as the developer to control the lifetime and completion of the associated Task. This includes SetResult, SetException, and SetCanceled, as well as TrySet* variants of each of those. (A Task may only be completed once, thus attempting to set a Task into a completed state when it’s already in a completed state is an error, and the Set* methods will throw. However, as we’re dealing with concurrency here, and there are some situations where races may be expected between multiple threads trying to resolve the completion source, the TrySet* variants return Booleans indicating success rather than throwing an exceptions.)&lt;/p&gt;  &lt;p&gt;As a simple example, imagine for a moment that you didn’t have Task.Factory.StartNew, and thus you needed a way to execute a Func&amp;lt;T&amp;gt; asynchronously and have a Task&amp;lt;T&amp;gt; to represent that operation. This could be done with a TaskCompletionSource&amp;lt;T&amp;gt; as follows:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;public static Task&amp;lt;T&amp;gt; RunAsync&amp;lt;T&amp;gt;(Func&amp;lt;T&amp;gt; function)     &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if (function == null) throw new ArgumentNullException(“function”);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; var tcs = new TaskCompletionSource&amp;lt;T&amp;gt;();      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ThreadPool.QueueUserWorkItem(_ =&amp;gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; try       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; T result = function();      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; tcs.SetResult(result);&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; catch(Exception exc) { tcs.SetException(exc); }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; });      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return tcs.Task;      &lt;br /&gt;}&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The operation is being performed asynchronously through a mechanism unknown to the TaskCompletionSource&amp;lt;T&amp;gt;. All it knows is that at some point, its SetResult or SetException method is being called to complete the Task&amp;lt;T&amp;gt; exposed through its Task property.&lt;/p&gt;  &lt;p&gt;Note, too, that because Task&amp;lt;TResult&amp;gt; derives from Task, we can use the generic TaskCompletionSource&amp;lt;TResult&amp;gt; under the covers for methods that work in terms of Task rather than in terms of Task&amp;lt;TResult&amp;gt;. For example, consider the same RunAsync method just shown, but accepting an Action (which returns void) rather than a Func&amp;lt;T&amp;gt; (which returns T).&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;public static Task RunAsync(Action action)     &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; var tcs = new TaskCompletionSource&amp;lt;Object&amp;gt;();      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ThreadPool.QueueUserWorkItem(_ =&amp;gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; try       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; action();      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; tcs.SetResult(null);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; catch(Exception exc) { tcs.SetException(exc); }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; });      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return tcs.Task;      &lt;br /&gt;}&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Since we no longer care what the type of T is, I’ve defaulted to using Object. Then, when the Action is executed successfully, SetResult is still used to transition the Task into the RanToCompletion final state; however, since the actual result value is irrelevant, null is used. Finally, RunAsync returns Task rather than Task&amp;lt;Object&amp;gt;. Of course, the instantiated task’s type is still Task&amp;lt;Object&amp;gt;, but we need not refer to it as such, and the consumer of this method need not care about those implementation details.&lt;/p&gt;  &lt;p&gt;In future posts, we’ll look at how TaskCompletionSource&amp;lt;TResult&amp;gt; is a staple in a developer’s toolbox, including the developers of the Task Parallel Library itself, where TaskCompletionSource&amp;lt;TResult&amp;gt; is used liberally internally.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9685804" 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></item><item><title>Tasks and Unhandled Exceptions</title><link>http://blogs.msdn.com/pfxteam/archive/2009/05/31/9674669.aspx</link><pubDate>Mon, 01 Jun 2009 04:34:11 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9674669</guid><dc:creator>toub</dc:creator><slash:comments>8</slash:comments><comments>http://blogs.msdn.com/pfxteam/comments/9674669.aspx</comments><wfw:commentRss>http://blogs.msdn.com/pfxteam/commentrss.aspx?PostID=9674669</wfw:commentRss><wfw:comment>http://blogs.msdn.com/pfxteam/rsscomments.aspx?PostID=9674669</wfw:comment><description>&lt;p&gt;Prior to the .NET Framework 2.0, unhandled exceptions were largely ignored by the runtime.&amp;#160; For example, if a work item queued to the ThreadPool threw an exception that went unhandled by that work item, the ThreadPool would eat that exception and continue on its merry way.&amp;#160; Similarly, if a finalizer running on the finalizer thread threw an exception, the system would eat the exception and continue on executing other finalizers.&lt;/p&gt;  &lt;p&gt;That changed for .NET 2.0.&amp;#160; Exceptions are meant to indicate a problem, and automatically eating unhandled exceptions often hides significant errors and reliability problems in an application.&amp;#160; As such, for .NET 2.0, this unhandled exception behavior was changed by default to more closely match how exceptions are handled by Windows in general: if an exception goes unhandled, the process comes crashing down.&amp;#160; While this may seem harsh, allowing the process to crash typically makes it easier to catch an underlying problem, but more importantly, it prevents the application from continuing to hobble along in a potentially very bad state, with corrupted data, etc.&amp;#160; Thus, since .NET 2.0, if a work item running on the ThreadPool throws an unhandled exception, by default the process crashes.&lt;/p&gt;  &lt;p&gt;There’s a notable exemption to this behavior, even after 2.0: the Asynchronous Programming Model (APM) pattern.&amp;#160; With the APM pattern, work is started asynchronously with a BeginXx method, and at some point later the results of the work are retrieved with a corresponding EndXx method.&amp;#160; If the asynchronous work throws an exception, that exception is then propagated out of the call to the EndXx method when the EndXx method is invoked.&amp;#160; This, of course, counts on the EndXx method being invoked.&amp;#160; If the developer makes a mistake such that End is never invoked, any exception that occurred as part of the asynchronous invocation will likely go unnoticed, as would have happened in more situations in .NET 1.x.&lt;/p&gt;  &lt;p&gt;With Tasks in .NET 4.0, we face a similar situation as does the APM pattern.&amp;#160; A Task represents an asynchronous operation that may throw an unhandled exception, but unlike work items generated by ThreadPool.QueueUserWorkItem, a Task instance is used to later join with the asynchronous work.&amp;#160; As such, any unhandled exceptions will be stored into the relevant Task instance, later thrown any time that Task is waited on (and also available through the Task’s Exception property).&amp;#160; In fire-and-forget scenarios, where the developer has no intention of joining with the Task, or if the developer simply forgets to join with the Task, the exception may never be observed, and thus if we did nothing special, we’d be in a bad situation very much like that which the APM pattern faces with unhandled exceptions.&lt;/p&gt;  &lt;p&gt;To address this, Tasks keep track of whether an unhandled exception has been “observed.”&amp;#160; In this context, “observed” means that code has joined with the Task in some fashion in order to at least be made aware of the exception.&amp;#160; This could be calling Wait/WaitAll on the Task.&amp;#160; It could be checking the Task’s Exception property after the Task has completed.&amp;#160; Or it could be using a Task&amp;lt;TResult&amp;gt;’s Result property.&amp;#160; If a Task sees that its exception has been observed in some manner, life is good.&amp;#160; If, however, all references to a Task are removed (making the Task available for garbage collection), and if its exception hasn’t yet been observed, the Task knows that its exception will never be observed.&amp;#160; In such a case, the Task takes advantage of finalization, and uses a helper object to propagate the unhandled exception on the finalizer thread.&amp;#160; With the behavior described earlier, that exception on the finalizer thread will go unhandled and invoke the default unhandled exception logic, which is to log the issue and crash the process.&lt;/p&gt;  &lt;p&gt;In this manner, we can have our cake and eat it, too.&amp;#160; As with the APM, we make any exceptions that occurred asynchronously available later for the app to retrieve.&amp;#160; And as with work items on the ThreadPool, if an exception goes unhandled, it will cause the process to be torn down.&lt;/p&gt;  &lt;p&gt;Of course, there may still be situations where you do want a fire-and-forget task, but where you want to automatically “observe” any unhandled exception, either to log it or something similar, or just to prevent the process from crashing in a situation where you know the exception will be benign.&amp;#160; In that case, you can take advantage of continuations to address your needs.&lt;/p&gt;  &lt;p&gt;Consider a Task &lt;em&gt;t&lt;/em&gt;.&amp;#160; After creating the Task, I can run code like the following:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;t.ContinueWith(c =&amp;gt; { var ignored = c.Exception; },      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; TaskContinuationOptions.OnlyOnFaulted |       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; TaskContinuationOptions.ExecuteSynchronously |      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; TaskContinuationOptions.DetachedFromParent);&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This code creates a continuation off of Task &lt;em&gt;t&lt;/em&gt; that will only be scheduled if Task &lt;em&gt;t&lt;/em&gt; completes in a Faulted state, meaning that it completed due to an exception going unhandled.&amp;#160; When this continuation runs, it will observe the Task’s exception, preventing it from getting finalized.&amp;#160; You could even wrap this kind of logic up into an extension method, such as:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;public static Task IgnoreExceptions(this Task task)      &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; task.ContinueWith(c =&amp;gt; { var ignored = c.Exception; },       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; TaskContinuationOptions.OnlyOnFaulted |       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; TaskContinuationOptions.ExecuteSynchronously |      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; TaskContinuationOptions.DetachedFromParent);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return task;       &lt;br /&gt;}&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;With this in hand, any time I create a fire-and-forget Task where I want an unhandled exception to be ignored, I can simply tag on IgnoreExceptions, e.g. instead of:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;var t = Task.Factory.StartNew(…);&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;I could write:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;var t = Task.Factory.StartNew(…).IgnoreExceptions();&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Of course, the exception handling logic in Task exists for good reasons, to prevent unhandled exceptions from going unnoticed, and as such it’s not a great idea to liberally sprinkle use of an IgnoreExceptions extension method like this.&amp;#160; But in some situations, it can be quite useful.&lt;/p&gt;  &lt;p&gt;There’s a corollary to IgnoreExceptions which may also be useful.&amp;#160; One of the downsides to the logic we use to tear down the process is that it relies on finalization.&amp;#160; Finalization isn’t guaranteed to occur in a timely fashion, so an exception may go unhandled and it may be some time before the app then crashes; some time is better than never, but it’s still not ideal.&amp;#160; If you want a more timely crash, you could use an extension method like the following:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;public static Task FailFastOnException(this Task task)      &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; task.ContinueWith(c =&amp;gt; Environment.FailFast(“Task faulted”, c.Exception),       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; TaskContinuationOptions.OnlyOnFaulted |       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; TaskContinuationOptions.ExecuteSynchronously |      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; TaskContinuationOptions.DetachedFromParent);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return task;       &lt;br /&gt;}&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Rather than ignoring the exception, this uses Environment.FailFast to immediately crash the process.&amp;#160; In this manner, I could write code like the following:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;var t = Task.Factory.StartNew(…).FailFastOnException();&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;and as soon as Task t faults, the process will crash.&amp;#160; This could be beneficial when debugging, as you’ll know immediately when something goes wrong.&amp;#160; There are lots of variations on this as well.&amp;#160; Debugger.Break could be used to immediately break into an attached debugger, you could raise an event of your choosing, the exception could be logged to an application log file, and so forth.&amp;#160; In this manner, continuations are quite powerful.&lt;/p&gt;  &lt;p&gt;(For anyone interested in extending Parallel Extensions with extension methods like this, the Parallel Extensions Extras project in the Beta 1 samples available at &lt;a title="http://code.msdn.microsoft.com/ParExtSamples" href="http://code.msdn.microsoft.com/ParExtSamples"&gt;http://code.msdn.microsoft.com/ParExtSamples&lt;/a&gt;&lt;strong&gt;&amp;#160;&lt;/strong&gt;includes a plethora of interesting and useful examples. Enjoy!)&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9674669" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Task+Parallel+Library/default.aspx">Task Parallel Library</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/ThreadPool/default.aspx">ThreadPool</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Code+Samples/default.aspx">Code Samples</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Parallel+Extensions/default.aspx">Parallel Extensions</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/.NET+4.0/default.aspx">.NET 4.0</category></item><item><title>ParallelOptions.MaxDegreeOfParallelism vs PLINQ’s WithDegreeOfParallelism</title><link>http://blogs.msdn.com/pfxteam/archive/2009/05/29/9655514.aspx</link><pubDate>Fri, 29 May 2009 17:20:18 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9655514</guid><dc:creator>toub</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/pfxteam/comments/9655514.aspx</comments><wfw:commentRss>http://blogs.msdn.com/pfxteam/commentrss.aspx?PostID=9655514</wfw:commentRss><wfw:comment>http://blogs.msdn.com/pfxteam/rsscomments.aspx?PostID=9655514</wfw:comment><description>&lt;p&gt;We exert a good deal of effort ensuring that the APIs we provide are consistent within Parallel Extensions as well as with the rest of the .NET Framework.&amp;#160; This is from many angles, including behavior and general design, but also naming.&amp;#160; So when there are slight differences in naming, it raises questions.&lt;/p&gt;  &lt;p&gt;One occurrence of such a slight naming difference is between the MaxDegreeOfParallelism property on ParallelOptions using by Parallel.For/ForEach/Invoke and the WithDegreeOfParallelism PLINQ extension method.&amp;#160; Why isn’t it ParallelOptions.DegreeOfParallelism, or WithMaxDegreeOfParallelism?&lt;/p&gt;  &lt;p&gt;The reason has to do with requirements imposed by the design of Parallel and PLINQ, the latter of which is a bit more restrictive in some ways.&amp;#160; Parallel works using an under-the-covers concept we refer to as replicating tasks.&amp;#160; The concept is that a loop will start with one task for processing the loop, but if more threads become available to assist in the processing, additional tasks will be created to run on those threads.&amp;#160; This enables minimization of resource consumption, e.g. if most of the threads in the ThreadPool are busy processing other work, a parallel loop that starts executing will execute with a smaller number of threads, until such time as the threads doing the rest of that processing are freed up and can assist in the execution of the loop.&amp;#160; Given this, it would be inaccurate to state that ParallelOptions enables the specification of a DegreeOfParallelism, because it’s really a maximum degree: the loop starts with a degree of 1, and may work its way up to any maximum that’s specified as resources become available.&lt;/p&gt;  &lt;p&gt;PLINQ is different.&amp;#160; Some important Standard Query Operators in PLINQ require communication between the threads involved in the processing of the query, including some that rely on a &lt;a href="http://msdn.microsoft.com/en-us/library/system.threading.barrier(VS.100).aspx"&gt;Barrier&lt;/a&gt; to enable threads to operate in lock-step.&amp;#160; The PLINQ design requires that a specific number of threads be actively involved for the query to make any progress.&amp;#160; Thus when you specify a DegreeOfParallelism for PLINQ, you’re specifying the actual number of threads that will be involved, rather than just a maximum.&lt;/p&gt;  &lt;p&gt;It’s conceivable that in the future, Parallel could be augmented to guarantee a certain number of threads involved, at which point a DegreeOfParallelism could be added, and it’s conceivable that in the future, PLINQ could be augmented to support varying number of threads over the lifetime of a query, at which point a WithMaxDegreeOfParallelism could be added.&amp;#160; In the end, the names were chosen to better convey exactly what’s happening in the systems, so that developers can set their expectations correctly.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9655514" 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/Parallel+Extensions/default.aspx">Parallel Extensions</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/.NET+4.0/default.aspx">.NET 4.0</category></item><item><title>Exiting from Parallel Loops Early</title><link>http://blogs.msdn.com/pfxteam/archive/2009/05/27/9645023.aspx</link><pubDate>Wed, 27 May 2009 21:56:11 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9645023</guid><dc:creator>toub</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/pfxteam/comments/9645023.aspx</comments><wfw:commentRss>http://blogs.msdn.com/pfxteam/commentrss.aspx?PostID=9645023</wfw:commentRss><wfw:comment>http://blogs.msdn.com/pfxteam/rsscomments.aspx?PostID=9645023</wfw:comment><description>&lt;p&gt;Exiting out of loops early is a fairly common pattern, one that doesn’t go away when parallelism is introduced.&amp;#160; To help simplify these use cases, the Parallel.For and Parallel.ForEach methods support several mechanisms for breaking out of loops early, each of which has different behaviors and targets different requirements.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Exceptions&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;In a sequential loop, an exception thrown from the loop causes the looping construct to immediately cease.&amp;#160; For our parallel loops, we’ve chosen to get as close to this as is possible while still being reliable and predictable.&amp;#160; This means that when an exception is thrown out of an iteration of a Parallel loop, the loop attempts to prevent additional iterations from starting, though it allows already started iterations to complete.&amp;#160; Once all iterations have ceased, the loop gathers up any exceptions that have been thrown, wraps them in a System.AggregateException and throws that aggregate out of the loop.&amp;#160; For cases where individual operations may run for a long time (and thus may delay the loop’s exit), overloads of Parallel.For and Parallel.ForEach exist that provide a ParallelLoopState instance to the body; this instance exposes an IsExceptional property, which indicates whether another iteration has thrown an unhandled exception.&amp;#160; Iterations may cooperatively check this property, allowing a long-running iteration to cooperatively exit early when it detects that another iteration has failed.&lt;/p&gt;  &lt;p&gt;While this exception logic does support exiting out of a loop early, it is not the recommended mechanism for doing so; rather, it exists purely to assist in exceptional cases, cases where you breaking out early wasn’t an intentional part of the algorithm.&amp;#160; As is the case with sequential constructs, exceptions should not be relied upon for control flow.&lt;/p&gt;  &lt;p&gt;Note that this exceptions behavior isn’t optional: there’s no way to tell the looping construct to delay the rethrowing of exceptions until the loop has completed, just as there’s no built-in way to do that with a sequential for loop.&amp;#160; If you wanted that behavior with a for loop, you’d likely end up writing code like the following:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;var exceptions = new Queue&amp;lt;Exception&amp;gt;();     &lt;br /&gt;for(int i=0; i&amp;lt;N; i++)      &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; try      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; … // loop body goes here      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; catch(Exception exc) { exceptions.Enqueue(exc); }      &lt;br /&gt;}      &lt;br /&gt;if (exceptions.Count &amp;gt; 0) throw new AggregateException(exceptions);&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;If this is the behavior you desire, that same manual handling is also possible using Parallel.For:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;var exceptions = new ConcurrentQueue&amp;lt;Exception&amp;gt;();     &lt;br /&gt;Parallel.For(0, N, i=&amp;gt;      &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; try      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; … // loop body goes here      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; catch(Exception exc) { exceptions.Enqueue(exc); }      &lt;br /&gt;});      &lt;br /&gt;if (!exceptions.IsEmpty) throw new AggregateException(exceptions);&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;strong&gt;Stop and Break&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;The ParallelLoopState referred to in the previous section on exceptions provides additional support for exiting loops early.&amp;#160; This support comes in the form of two methods and two properties: Stop(), Break(), IsStopped, and LowestBreakIteration.&lt;/p&gt;  &lt;p&gt;If a loop iteration calls Stop, the loop will attempt to prevent more iterations from starting.&amp;#160; Once there are no more iterations executing, the loop will return successfully (i.e. without an exception).&amp;#160; The return type of Parallel.For and Parallel.ForEach is a ParallelLoopResult struct: if Stop caused the loop to exit early, this result’s IsCompleted property will return false.&amp;#160; As with exceptions, where an IsExceptional property enables other running iterations to cooperatively detect an exception from another iteration, the IsStopped property enables an iteration to detect when another iteration has called Stop.&lt;/p&gt;  &lt;p&gt;Break is very similar to stop, except it provides extra guarantees.&amp;#160; Whereas Stop informs the loop that no more iterations need be executed such that the loop can cease execution as soon as possible, Break informs the loop that no iterations after the current one (e.g. where the iteration number is higher, or where the data comes after the current element in the data source) need be run, but that iterations prior to the current one still need to be run.&amp;#160; Break may be called from multiple iterations, and the lowest iteration from which Break was called is the one that takes effect; this iteration number can be retrieved from the ParallelLoopState’s LowestBreakIteration property, a nullable value.&lt;/p&gt;  &lt;p&gt;If the ParallelLoopResult’s IsCompleted property returns true, all of the iterations were processed.&amp;#160; If IsCompleted returns false and LowestBreakIteration.HasValue is false, Stop was used to exit the loop early.&amp;#160; If IsCompleted returns false and LowestBreakIteration.HasValue is true, Break was used to exit the loop early.&lt;/p&gt;  &lt;p&gt;Stop is typically useful for unordered search scenarios, where the loop is looking for something and can bail as soon as it finds it.&amp;#160; Break is typically useful for ordered search scenarios, where all of the data up until some point in the source needs to be processed, with that point based on some search criteria.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;CancellationToken&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;All of the previous mentioned mechanisms are based on the body of the loop exiting early, i.e. the body of the loop may throw an unhandled exception, may call Stop, or may call Break.&amp;#160; Sometimes, however, we want an entity external to the loop to be able to terminate the loop; this is known as cancellation.&lt;/p&gt;  &lt;p&gt;Cancellation is supported in parallel loops through the new &lt;a href="http://blogs.msdn.com/pfxteam/archive/2009/05/22/9635790.aspx"&gt;System.Threading.CancellationToken type introduced in .NET 4.0&lt;/a&gt;.&amp;#160; Overloads of all of the methods on Parallel accept a ParallelOptions instance, and one of the properties on ParallelOptions is a CancellationToken.&amp;#160; Simply set this CancellationToken property to the CancellationToken that should be monitored for cancellation, and provide that options instance to the loop’s invocation.&amp;#160; The loop will monitor the token, and if it finds that cancellation has been requested, it will again stop launching more iterations, wait for all existing iterations to complete, and then throw an OperationCanceledException.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Employing Multiple Exit Strategies&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;It’s possible that multiple exit strategies could all be employed concurrently; we’re dealing with parallelism after all.&amp;#160; In such cases, exceptions always win: if an unhandled exception has occurred, the loop will always propagate those exceptions, regardless of whether Stop or Break was called or whether cancellation was requested.&amp;#160; &lt;/p&gt;  &lt;p&gt;If no exceptions occurred but the CancellationToken was signaled and either Stop or Break was used, there’s a potential race as to whether the loop will notice the cancellation prior to exiting.&amp;#160; If it does, the loop will exit with an OperationCanceledException.&amp;#160; If it doesn’t, it will exit from the Stop/Break as explained above.&lt;/p&gt;  &lt;p&gt;Note, though, that Stop and Break may not be used together.&amp;#160; If the loop detects that one iteration called Stop while another called Break, the invocation of whichever method ended up being invoked second will result in an exception being thrown.&lt;/p&gt;  &lt;p&gt;Finally, for long running iterations, there are multiple properties an iteration might want to check to see whether it should bail early: IsExceptional, IsStopped, LowestBreakIteration, etc.&amp;#160; To simplify this, ParallelLoopState also provides a ShouldExitCurrentIteration property, which consolidates all of those checks.&amp;#160; The loop itself checks this value prior to invoking iterations.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9645023" 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></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 15: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 03: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 00: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></channel></rss>