{"id":2763,"date":"2008-02-29T15:20:00","date_gmt":"2008-02-29T15:20:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/pfxteam\/2008\/02\/29\/implementing-the-asynchronous-programming-model-with-futuret\/"},"modified":"2008-02-29T15:20:00","modified_gmt":"2008-02-29T15:20:00","slug":"implementing-the-asynchronous-programming-model-with-futuret","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/implementing-the-asynchronous-programming-model-with-futuret\/","title":{"rendered":"Implementing the Asynchronous Programming Model with Future"},"content":{"rendered":"<p>One of our design goals for the Task Parallel Library is to integrate well into existing asynchronous mechanisms in the .NET Framework.&nbsp; And one of the most common concurrency-related patterns in the .NET Framework is the Asynchronous Programming Model (APM), which typically manifests as a BeginXx method that kicks off an asynchronous operation and returns an IAsyncResult, along with an EndXx method that accepts an IAsyncResult and returns the computed value.<\/p>\n<p>Implementing this for computationally intensive asynchronous operations can be done with System.Threading.Tasks.Future&lt;T&gt;, as Future&lt;T&gt; derives from System.Threading.Tasks.Task, and Task implements IAsyncResult.&nbsp; Imagine you had a class used for computing the value of pi to an arbitrary number of decimal places:<\/p>\n<blockquote>\n<p class=\"MsoNormal\"><span>public<\/span><span> <span>class<\/span> <span>PI<br><\/span><\/span><span>{<br><\/span><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>public<\/span> <span>string<\/span> Calculate(<span>int<\/span> decimalPlaces) { &#8230; }<\/span><span><br><\/span><span>}<\/span><\/p>\n<\/blockquote>\n<p>We can add BeginCalculate and EndCalculate methods that provide a trimmed-down implementation of the APM for Calculate with only a few lines of code:<\/p>\n<blockquote>\n<p class=\"MsoNormal\"><span>public<\/span><span> <span>class<\/span> <span>PI<br><\/span><\/span><span>{<br><\/span><span>&nbsp;&nbsp;&nbsp; &#8230;<\/p>\n<p><\/span><span><\/p>\n<p>&nbsp; <\/p>\n<p><\/span><span><span>&nbsp; <\/span><span>public<\/span> <span>IAsyncResult<\/span> BeginCalculate(<span>int<\/span> decimalPlaces)<br><\/span><span><span>&nbsp;&nbsp;&nbsp; <\/span>{<br><\/span><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>return<\/span> <span>Future<\/span>.Create(() =&gt; Calculate(decimalPlaces));<br><\/span><span><span>&nbsp;&nbsp;&nbsp; <\/span>}<\/span><span><\/p>\n<p>&nbsp;<br><\/p>\n<p><\/span><span><span><br>&nbsp;&nbsp;&nbsp; <\/span><span>public<\/span> <span>string<\/span> EndCalculate(<span>IAsyncResult<\/span> ar)<br><\/span><span><span>&nbsp;&nbsp;&nbsp; <\/span>{<br><\/span><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>var<\/span> f = ar <span>as<\/span> <span>Future<\/span>&lt;<span>string<\/span>&gt;;<br><\/span><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>if<\/span> (f == <span>null<\/span>) <span>throw<\/span> <span>new<\/span> <span>ArgumentException<\/span>(<span>&#8220;ar&#8221;<\/span>);<br><\/span><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>return<\/span> f.Value;<br><\/span><span><span>&nbsp;&nbsp;&nbsp; <\/span>}<br><\/span><span>}<\/span><\/p>\n<\/blockquote>\n<p>However, the full APM pattern dictates that BeginXx should also accept an AsyncCallback that is invoked when the operation completes, along with some user-defined state.&nbsp; The AsyncCallback addition is easy to implement with the current design of Future&lt;T&gt;:<\/p>\n<blockquote>\n<p class=\"MsoNormal\"><span>public<\/span><span> <span>IAsyncResult<\/span> BeginCalculate(<br>&nbsp;&nbsp;&nbsp; <span>int<\/span> decimalPlaces, <span>AsyncCallback<\/span> ac)<br><\/span><span>{<br><\/span><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>var<\/span> f = <span>Future<\/span>.Create(() =&gt; Calculate(decimalPlaces));<br><\/span><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>if<\/span> (ac != <span>null<\/span>) f.Completed += <span>delegate<\/span> { ac(f); };<br><\/span><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>return<\/span> f;<br><\/span><span>}<\/span><\/p>\n<\/blockquote>\n<p>I simply register with the Future&lt;T&gt;&#8217;s Completed event such that when the Future&lt;T&gt; completes, it invokes the AsyncCallback.&nbsp; Easy enough.&nbsp; Unfortunately, with the current design of Future&lt;T&gt;, supporting the state argument is more difficult, since unlike Task, none of the factories for Future&lt;T&gt; accept an arbitrary state argument (this is something we&#8217;re planning to rectify).&nbsp; For now with the current CTP bits, you can work around this by creating your own small wrapper for the Future&lt;T&gt; and the state object:<\/p>\n<blockquote>\n<p class=\"MsoNormal\"><span>private<\/span><span> <span>class<\/span> <span>FutureWithState<\/span>&lt;T&gt; : <span>IAsyncResult<br><\/span><\/span><span>{<br><\/span><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>public<\/span>&nbsp;<span>IAsyncResult<\/span> Future;<br><\/span><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>public<\/span> <span>object<\/span> State;<\/span><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>public<\/span> <span>object<\/span> AsyncState { <span>get<\/span> { <span>return<\/span> State; } }<br><\/span><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>public<\/span> <span>WaitHandle<\/span> AsyncWaitHandle { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>get<\/span> { <span>return<\/span> Future.AsyncWaitHandle; } }<br><\/span><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>public<\/span> <span>bool<\/span> CompletedSynchronously { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span><span>get<\/span> { <span>return<\/span> Future.CompletedSynchronously; } }<br><\/span><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>public<\/span> <span>bool<\/span> IsCompleted { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>get<\/span> { <span>return<\/span> Future.IsCompleted; } }<br><\/span><span>}<\/span><\/p>\n<\/blockquote>\n<p>The modifications to our implementations of BeginCalculate and EndCalculate to support state are then very straightforward:<\/p>\n<blockquote>\n<p class=\"MsoNormal\"><span>public<\/span><span> <span>IAsyncResult<\/span> BeginCalculate(<br>&nbsp;&nbsp;&nbsp; <span>int<\/span> decimalPlaces, <span>AsyncCallback<\/span> ac, <span>object<\/span> state)<br><\/span><span>{<br><\/span><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>var<\/span> f = <span>Future<\/span>.Create(() =&gt; Calculate(decimalPlaces));<\/span><span><br><\/span><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>var <font color=\"#000000\">fws = <\/font><\/span><span>new<\/span> <span>FutureWithState<\/span>&lt;<span>string<\/span>&gt; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Future = f, State = state };<br><\/span><span><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>if<\/span> (ac != <span>null<\/span>) f.Completed += <span>delegate<\/span> { ac(fws); };<br>&nbsp;&nbsp;&nbsp; <span>return <\/span>fws;<\/span><\/span><span><br><\/span><span>}<\/p>\n<p><\/span><span>public<\/span><span> <span>string<\/span> EndCalculate(<span>IAsyncResult<\/span> ar)<br><\/span><span>{<br><\/span><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>var<\/span> f = ar <span>as<\/span> <span>FutureWithState<\/span>&lt;<span>string<\/span>&gt;;<br><\/span><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>if<\/span> (f == <span>null<\/span>) <span>throw<\/span> <span>new<\/span> <span>ArgumentException<\/span>(<span>&#8220;ar&#8221;<\/span>);<br><\/span><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>return<\/span> f.Future.Value;<br><\/span><span>}<\/span><\/p>\n<\/blockquote>\n<p>This same container approach can work for scenarios where you want to store more arbitrary state with your IAsyncResult.<\/p>\n<p>Note, too, that Future&lt;T&gt; can also be used for situations where the asynchronous work isn&#8217;t computationally intensive.&nbsp; Consider the System.Net.NetworkInformation.Ping class that was introduced in the .NET Framework 2.0.&nbsp; Rather than following the APM pattern, Ping derives from Component and follows the Event-based Asynchronous Pattern (EAP).&nbsp; So rather than exposing BeginSend and EndSend methods that deal with IAsyncResults, it exposes a SendAsync method that returns void, along with a PingCompleted event that is raised when the asynchronous ping send operation completes.&nbsp; What if we wanted to use asynchronous pings, but we wanted to expose them through the APM pattern.&nbsp; We could easily implement this with Future&lt;T&gt; as follows:<\/p>\n<blockquote>\n<p class=\"MsoNormal\"><span>public<\/span><span> <span>class<\/span> <span>MyPing<br><\/span><\/span><span>{<br><\/span><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>public<\/span> <span>IAsyncResult<\/span> BeginPing(<span>string<\/span> host)<br><\/span><span><span>&nbsp;&nbsp;&nbsp; <\/span>{<br><\/span><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>return<\/span> <span>Future<\/span>.Create(() =&gt; <span>new<\/span> <span>Ping<\/span>().Send(host));<br><\/span><span><span>&nbsp;&nbsp;&nbsp; <\/span>}<\/span><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>public<\/span> <span>PingReply<\/span> EndPing(<span>IAsyncResult<\/span> ar)<br><\/span><span><span>&nbsp;&nbsp;&nbsp; <\/span>{<br><\/span><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>var<\/span> f = ar <span>as<\/span> <span>Future<\/span>&lt;<span>PingReply<\/span>&gt;;<br><\/span><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>if<\/span> (f == <span>null<\/span>) <span>throw<\/span> <span>new<\/span> <span>ArgumentException<\/span>(<span>&#8220;ar&#8221;<\/span>);<br><\/span><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>return<\/span> f.Value;<br><\/span><span><span>&nbsp;&nbsp;&nbsp; <\/span>}<br><\/span><span>}<\/span><\/p>\n<\/blockquote>\n<p>but this has some serious downsides: foremost, the implementation of Send is not computationally intensive, and yet the Future&lt;T&gt; is going to be using and blocking a thread to do a synchronous send.&nbsp; What we really want to do is take full advantage of Ping&#8217;s asynchronous send implementation.&nbsp; And we can do that by using Future&lt;T&gt;&#8217;s &#8220;promise&#8221; capabilities:<\/p>\n<blockquote>\n<p class=\"MsoNormal\"><span>public<\/span><span> <span>class<\/span> <span>MyPing<br><\/span><\/span><span>{<br><\/span><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>public<\/span> <span>IAsyncResult<\/span> BeginPing(<span>string<\/span> host, <span>AsyncCallback<\/span> ac)<br><\/span><span><span>&nbsp;&nbsp;&nbsp; <\/span>{<\/span><span><br><\/span><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>var<\/span> f = <span>Future<\/span>&lt;<span>PingReply<\/span>&gt;.Create();<br><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>if<\/span> (ac != <span>null<\/span>) f.Completed += <span>delegate<\/span> { ac(f); };<br><\/span><br><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&nbsp;<\/span><span>Ping<\/span> p = <span>new<\/span> <span>Ping<\/span>();<\/span><br><\/span><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>p.PingCompleted += (sender, state) =&gt;<br><\/span><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>{<br><\/span><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>if<\/span> (state.Error != <span>null<\/span>) f.Exception = state.Error;<br><\/span><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>else<\/span> f.Value = state.Reply;<\/span><span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>};<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p.SendAsync(host, <span>null<\/span>);<br><\/span><span><br><\/span><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>return<\/span> f;<br><\/span><span><span>&nbsp;&nbsp;&nbsp; <\/span>}<\/span><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>public<\/span> <span>PingReply<\/span> EndPing(<span>IAsyncResult<\/span> ar)<br><\/span><span><span>&nbsp;&nbsp;&nbsp; <\/span>{<br><\/span><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>var<\/span> f = ar <span>as<\/span> <span>Future<\/span>&lt;<span>PingReply<\/span>&gt;;<br><\/span><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>if<\/span> (f == <span>null<\/span>) <span>throw<\/span> <span>new<\/span> <span>ArgumentException<\/span>(<span>&#8220;ar&#8221;<\/span>);<br><\/span><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>return<\/span> f.Value;<br><\/span><span><span>&nbsp;&nbsp;&nbsp; <\/span>}<br><\/span><span>}<\/span><\/p>\n<\/blockquote>\n<p>The Future&lt;T&gt; I create here has no delegate associated with it.&nbsp; Instead, it allows its Value and Exception properties to be set (only once), and someone waiting on Future&lt;T&gt;&#8217;s Value will block until either Exception or Value is set.&nbsp; I take advantage of that by setting these properties in the PingCompleted event handler.&nbsp; With very little code, I now can get a fully-working IAsyncResult that represents an asynchronous ping, where the original asynchronous behavior was exposed through a different mechanism.<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>One of our design goals for the Task Parallel Library is to integrate well into existing asynchronous mechanisms in the .NET Framework.&nbsp; And one of the most common concurrency-related patterns in the .NET Framework is the Asynchronous Programming Model (APM), which typically manifests as a BeginXx method that kicks off an asynchronous operation and returns [&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":[7911,7909,7912],"class_list":["post-2763","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-pfxteam","tag-code-samples","tag-parallel-extensions","tag-task-parallel-library"],"acf":[],"blog_post_summary":"<p>One of our design goals for the Task Parallel Library is to integrate well into existing asynchronous mechanisms in the .NET Framework.&nbsp; And one of the most common concurrency-related patterns in the .NET Framework is the Asynchronous Programming Model (APM), which typically manifests as a BeginXx method that kicks off an asynchronous operation and returns [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/2763","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=2763"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/2763\/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=2763"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=2763"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=2763"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}