{"id":3033,"date":"2015-02-02T07:31:00","date_gmt":"2015-02-02T07:31:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/pfxteam\/2015\/02\/02\/new-task-apis-in-net-4-6\/"},"modified":"2015-02-02T07:31:00","modified_gmt":"2015-02-02T07:31:00","slug":"new-task-apis-in-net-4-6","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/new-task-apis-in-net-4-6\/","title":{"rendered":"New Task APIs in .NET 4.6"},"content":{"rendered":"<p>There are several nice API-level enhancements to the Task Parallel Library in .NET 4.6, which you can <a href=\"https:\/\/www.visualstudio.com\/news\/vs2015-vs\">grab a preview<\/a> of as part of the Visual Studio 2015 CTP.<\/p>\n<p><strong>Task.From*<\/strong><\/p>\n<p>.NET 4.5 had a Task.FromResult method. \u00a0This method makes it quick and easy to manufacture a new Task for a known result value, and is particularly useful when implementing a Task-returning method to complete synchronously. \u00a0However, Task didn&#8217;t expose corresponding methods for creating canceled or faulted tasks; instead, developers needed to manually create such tasks, such as by using a TaskCompletionSource, e.g.<\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: 'courier new', courier\">public static Task&lt;TResult&gt; FromException&lt;TResult&gt;(Exception exc)<\/span>\n<span style=\"font-family: 'courier new', courier\">{<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 var tcs = new TaskCompletionSource&lt;TResult&gt;();<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 tcs.SetException(exc);<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 return tcs.Task;<\/span>\n<span style=\"font-family: 'courier new', courier\">}<\/span><\/p>\n<p>Now in .NET 4.6, developers no longer need to write this boilerplate, as Task exposes several new static helpers, Task.FromCanceled and Task.FromException. \u00a0Imagine you were implementing a Stream-derived type whose Read method simply read and returned some data already in memory; it would likely be more efficient for ReadAsync to simply do the work synchronously rather than scheduling the memory reads to be done asynchronously. \u00a0Such functionality can now be done with fairly minimal boilerplate using these new APIs, e.g.<\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: 'courier new', courier\">public class MyMemoryStream : Stream<\/span>\n<span style=\"font-family: 'courier new', courier\">{<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 &#8230;<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 public override Task&lt;int&gt; ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 {<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 \u00a0 \u00a0 if (cancellationToken.IsCancellationRequested)<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return Task.FromCanceled&lt;int&gt;(cancellationToken);<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 \u00a0 \u00a0 try<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 \u00a0 \u00a0 {<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return Task.FromResult(Read(buffer, offset, count));<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 \u00a0 \u00a0 }<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 \u00a0 \u00a0 catch (Exception exc)<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 \u00a0 \u00a0 {<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return Task.FromException(exc);<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 \u00a0 \u00a0 }<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 }<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 &#8230;<\/span>\n<span style=\"font-family: 'courier new', courier\">}<\/span><\/p>\n<p><strong>Task.CompletedTask<\/strong><\/p>\n<p>In particular in library code that cares about performance and avoiding allocations, it&#8217;s frequently desired to implement fast-paths that, when possible, use cached already-completed tasks. \u00a0This is particularly true for a successfully-completed, non-generic Task. \u00a0Previously code that wanted such a cached task would often stash one in a static, e.g.<\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: 'courier new', courier\">private static readonly Task s_completedTask = Task.FromResult(true);<\/span>\n<span style=\"font-family: 'courier new', courier\">&#8230;<\/span>\n<span style=\"font-family: 'courier new', courier\">return s_completedTask;\u00a0<\/span><\/p>\n<p>or it would rely on a method in the framework that the a developer knew (or hoped) would use such a cached task, e.g.<\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: 'courier new', courier\">return Task.Delay(0);<\/span><\/p>\n<p>With .NET 4.6, such a cached task has been exposed from the new Task.CompletedTask property.<\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: 'courier new', courier\">return Task.CompletedTask;<\/span><\/p>\n<p><strong>Task{Creation\/Continuation}Options.RunContinuationsAsynchronously<\/strong><\/p>\n<p>TaskCompletionSource&lt;TResult&gt; is very helpful in building Task-returning methods to wrap other asynchronous operations. \u00a0It&#8217;s also helpful in building asynchronous data structures and synchronization primitives. \u00a0I previously blogged about building such synchronization primitives, such as <a href=\"https:\/\/blogs.msdn.com\/b\/pfxteam\/archive\/2012\/02\/11\/10266923.aspx\">building an AsyncAutoResetEvent<\/a>. \u00a0In that post, I noted that I had to be careful about where I invoked the TaskCompletionSource&lt;TResult&gt;.SetResult method:<\/p>\n<p style=\"padding-left: 30px\"><em>&#8220;I talked about a ramification of calling {Try}Set* methods on TaskCompletionSource&lt;TResult&gt;, that any synchronous continuations off of the TaskCompletionSource&lt;TResult&gt;\u2019s Task could run synchronously as part of the call.\u00a0 If we were to invoke SetResult here while holding the lock, then synchronous continuations off of that Task would be run while holding the lock, and that could lead to very real problems.\u00a0 So, while holding the lock we grab the TaskCompletionSource&lt;bool&gt; to be completed, but we don\u2019t complete\u00a0 it yet, delaying doing so until the lock has been released&#8221;<\/em><\/p>\n<p>This is a not-uncommon issue that folks using TaskCompletionSource to build such types face and need to work around. \u00a0In this particular case, I avoided the cited problem by storing the TaskCompletionSource&lt;TResult&gt; into a local and then waiting until outside of the lock to call SetResult, so that synchronous continuations didn&#8217;t run on the thread calling SetResult while it held the lock. \u00a0That solved that particular problem, but there are others folks often need to work around as well. \u00a0For example, if you don&#8217;t want your code calling SetResult to have to wait for all synchronous continuations to complete before SetResult returns, you have to explicitly queue the call to SetResult so that the Task completion runs asynchronously from the caller and thus so do the continuations. \u00a0You can see an example of this in TPL Dataflow, with its <a href=\"https:\/\/github.com\/dotnet\/corefx\/blob\/master\/src\/System.Threading.Tasks.Dataflow\/src\/Base\/DataflowBlock.cs#L525\">RunCompletionAction method<\/a> that takes a runAsync argument which will be set to true by callers that can&#8217;t afford to have continuations run synchronously as part of completing the task.<\/p>\n<p>You can see another <a href=\"http:\/\/referencesource.microsoft.com\/#mscorlib\/system\/threading\/SemaphoreSlim.cs,815\">example of this in SemaphoreSlim.Release<\/a>. \u00a0SemaphoreSlim.<a href=\"https:\/\/blogs.msdn.com\/b\/pfxteam\/archive\/2012\/02\/29\/10274035.aspx\">WaitAsync<\/a>\/Release are often used in async methods to provide mutual exclusion without blocking, e.g.<\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: 'courier new', courier\">private SemaphoreSlim _gate = new SemaphoreSlim(1, 1);<\/span>\n<span style=\"font-family: 'courier new', courier\">&#8230;<\/span>\n<span style=\"font-family: 'courier new', courier\">private async Task WorkAsync()<\/span>\n<span style=\"font-family: 'courier new', courier\">{<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 await _gate.WaitAsync().ConfigureAwait(false);<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 try<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 {<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 \u00a0 \u00a0 &#8230; \/\/ work here<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 }<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 finally { _gate.Release(); }<\/span>\n<span style=\"font-family: 'courier new', courier\">}<\/span><\/p>\n<p>Now imagine that you have lots of calls to WorkAsync:<\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: 'courier new', courier\">await Task.WhenAll(from i in Enumerable.Range(0, 10000) select WorkAsync());<\/span><\/p>\n<p>We&#8217;ve just created 10,000 calls to WorkAsync that will be appropriately serialized on the semaphore. \u00a0One of the tasks will enter the critical region, and the others will queue up on the WaitAsync call, inside SemaphoreSlim effectively enqueueing the task to be completed when someone calls Release. \u00a0If Release completed that Task synchronously, then when the first task calls Release, it&#8217;ll synchronously start executing the second task, and when it calls Release, it&#8217;ll synchronously start executing the third task, and so on. \u00a0If the &#8220;\/\/work here&#8221; section of code above didn&#8217;t include any awaits that yielded, then we&#8217;re potentially going to stack dive here and eventually potentially blow out the stack. \u00a0In large part for this reason, SemaphoreSlim.Release doesn&#8217;t actually complete the task synchronously; rather, Release queues the completion of the task so that it happens asynchronously from the caller.<\/p>\n<p>To make these kinds of issues easier to address, and also to make them a bit more obvious, in .NET 4.6 the TaskCreationOptions and TaskContinuationOptions enums include a new value: RunContinuationsAsynchronously. \u00a0When a Task created with this option completes, it won&#8217;t even try to invoke continuations synchronously&#8230; it&#8217;ll simply invoke all of the continuations asynchronously as if none had asked to be executed synchronously if possible. \u00a0There are already multiple reasons why a continuation that requested synchronous execution may not run synchronously, e.g. if the TaskScheduler denies it, and now the developer creating the task can explicitly deny such requests.<\/p>\n<p>TaskCompletionSource&lt;TResult&gt; has a constructor that takes a TaskCreationOptions value, so this option can easily be used with tasks created by TaskCompletionSource&lt;TResult&gt;. \u00a0Returning to the aforementioned AsyncAutoResetEvent as an example, we can tweak its implementation to use this new option:<\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: 'courier new', courier\">public Task WaitAsync()<\/span>\n<span style=\"font-family: 'courier new', courier\">{<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 lock (m_waits)<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 {<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 \u00a0 \u00a0 if (m_signaled)<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 \u00a0 \u00a0 {<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 m_signaled = false;<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return s_completed;<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 \u00a0 \u00a0 }<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 \u00a0 \u00a0 else<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 \u00a0 \u00a0 {<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 var tcs = new TaskCompletionSource&lt;bool&gt;(<strong>TaskCreationOptions.RunContinuationsAsynchronously<\/strong>);<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 m_waits.Enqueue(tcs);<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return tcs.Task;<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 \u00a0 \u00a0 }<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 }<\/span>\n<span style=\"font-family: 'courier new', courier\">}<\/span><\/p>\n<p><span style=\"font-family: 'courier new', courier\">public void Set()<\/span>\n<span style=\"font-family: 'courier new', courier\">{<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 lock (m_waits)<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 {<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 \u00a0 \u00a0 if (m_waits.Count &gt; 0)<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 m_waits.Dequeue()<strong>.SetResult(true)<\/strong>;<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 \u00a0 \u00a0 else if (!m_signaled)<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 m_signaled = true;<\/span>\n<span style=\"font-family: 'courier new', courier\">\u00a0 \u00a0 }<\/span>\n<span style=\"font-family: 'courier new', courier\">}<\/span><\/p>\n<p>Enjoy!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>There are several nice API-level enhancements to the Task Parallel Library in .NET 4.6, which you can grab a preview of as part of the Visual Studio 2015 CTP. Task.From* .NET 4.5 had a Task.FromResult method. \u00a0This method makes it quick and easy to manufacture a new Task for a known result value, and is [&hellip;]<\/p>\n","protected":false},"author":360,"featured_media":58792,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[7908],"tags":[7912],"class_list":["post-3033","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-pfxteam","tag-task-parallel-library"],"acf":[],"blog_post_summary":"<p>There are several nice API-level enhancements to the Task Parallel Library in .NET 4.6, which you can grab a preview of as part of the Visual Studio 2015 CTP. Task.From* .NET 4.5 had a Task.FromResult method. \u00a0This method makes it quick and easy to manufacture a new Task for a known result value, and is [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/3033","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/360"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=3033"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/3033\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/58792"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=3033"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=3033"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=3033"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}