{"id":56025,"date":"2012-02-06T13:25:52","date_gmt":"2012-02-06T13:25:52","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/pfxteam\/2012\/02\/06\/fromasyncasyncresult-vs-fromasyncbeginmethod\/"},"modified":"2012-02-06T13:25:52","modified_gmt":"2012-02-06T13:25:52","slug":"fromasyncasyncresult-vs-fromasyncbeginmethod","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/fromasyncasyncresult-vs-fromasyncbeginmethod\/","title":{"rendered":"FromAsync(asyncResult, \u2026) vs FromAsync(beginMethod, \u2026)"},"content":{"rendered":"<p>The Task Parallel Library (TPL) provides a set of &ldquo;<a href=\"https:\/\/blogs.msdn.com\/b\/pfxteam\/archive\/2009\/06\/09\/9716439.aspx\">FromAsync<\/a>&rdquo; helper methods that create a Task or a Task&lt;TResult&gt; to represent an invocation of an APM method pair, i.e. BeginXx \/ EndXx.&nbsp; There are, however, <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.threading.tasks.taskfactory.fromasync.aspx\">two different flavors<\/a> among these overloads: ones that accept an IAsyncResult &ldquo;asyncResult&rdquo; as the first parameter, and ones that accept a Func&lt;&hellip;,AsyncCallback,object,IAsyncResult&gt; &ldquo;beginMethod&rdquo; as the first parameter.&nbsp; What&rsquo;s the difference, and why would you choose one over the other?<\/p>\n<p>The fundamental difference between the two is in how the endMethod delegate is invoked.&nbsp; When FromAsync is given a beginMethod delegate, it passes to that beginMethod an AsyncCallback that will invoke the endMethod.&nbsp; As with any APM implemention, it&rsquo;s up to the BeginXx&rsquo;s implementation to eventually invoke this AsyncCallback when the async operation has completed.&nbsp; In contrast, the IAsyncResult interface doesn&rsquo;t provide any mechanism via which to provide a callback that will be invoked when the operation represented by the IAsyncResult is completed, so when FromAsync is handed an IAsyncResult, it needs to monitor the IAsyncResult&rsquo;s WaitHandle.<\/p>\n<p>Monitoring the IAsyncResult&rsquo;s WaitHandle (as returned from its AsyncWaitHandle property) has a few implications.&nbsp; First, since the APM pattern is all about asynchrony, most IAsyncResult implementations strive to avoid allocating the WaitHandle, only doing so lazily if it&rsquo;s actually requested.&nbsp; Thus, by accessing the IAsyncResult&rsquo;s AsyncWaitHandle property, FromAsync is likely forcing allocation of a WaitHandle (and the associated operating system primitives) that otherwise wouldn&rsquo;t need to be allocated.&nbsp; Second, the only way to &ldquo;monitor&rdquo; a WaitHandle to know when it&rsquo;s been set is to wait on it, which is a potentially blocking operation.&nbsp; Obviously, FromAsync isn&rsquo;t going to block the current thread by waiting on this handle (that wouldn&rsquo;t be very async of it), so instead it relies on the ThreadPool.&nbsp; It could queue a work item to block on the handle, but that would end up burning a ThreadPool thread for each such call.&nbsp; Instead, FromAsync relies on <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/hka8cs9z.aspx\">ThreadPool.RegisterWaitForSingleObject<\/a>, a function that is specifically geared towards using the ThreadPool to more efficiently wait for handles. According to the MSDN documentation, it does so by waiting on multiple handles from a single thread via WaitForMultipleObjects; however, there are a limit to how many handles it can wait on from each thread, so while this will end up burning fewer threads than if we blocked one thread per handle, it&rsquo;s still far from ideal.<\/p>\n<p>As such, if you have a choice between using FromAsync(asyncResult, &hellip;) and using FromAsync(beginMethod, &hellip;), pick the latter that uses a delegate instead of an IAsyncResult.&nbsp; When might you choose to use the former?&nbsp; The IAsyncResult overloads can still be useful in a few cases.&nbsp; For example, there are some BeginXx methods with signatures that don&rsquo;t exactly conform to the beginMethod functions accepted by the built-in FromAsync overloads, e.g. they have more parameters than the built-in versions can handle.&nbsp; In such a case, you could choose to either write your own FromAsync method to accommodate the custom signature, or you could use an IAsyncResult overload, since it doesn&rsquo;t care about the shape of the BeginXx method, only about its result.<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>The Task Parallel Library (TPL) provides a set of &ldquo;FromAsync&rdquo; helper methods that create a Task or a Task&lt;TResult&gt; to represent an invocation of an APM method pair, i.e. BeginXx \/ EndXx.&nbsp; There are, however, two different flavors among these overloads: ones that accept an IAsyncResult &ldquo;asyncResult&rdquo; as the first parameter, and ones that accept [&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":[7907,7925,36,7909,7912],"class_list":["post-56025","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-pfxteam","tag-net-4","tag-net-4-5","tag-async","tag-parallel-extensions","tag-task-parallel-library"],"acf":[],"blog_post_summary":"<p>The Task Parallel Library (TPL) provides a set of &ldquo;FromAsync&rdquo; helper methods that create a Task or a Task&lt;TResult&gt; to represent an invocation of an APM method pair, i.e. BeginXx \/ EndXx.&nbsp; There are, however, two different flavors among these overloads: ones that accept an IAsyncResult &ldquo;asyncResult&rdquo; as the first parameter, and ones that accept [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/56025","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=56025"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/56025\/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=56025"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=56025"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=56025"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}