{"id":56023,"date":"2012-02-08T09:02:24","date_gmt":"2012-02-08T09:02:24","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/pfxteam\/2012\/02\/08\/potential-pitfalls-to-avoid-when-passing-around-async-lambdas\/"},"modified":"2012-02-08T09:02:24","modified_gmt":"2012-02-08T09:02:24","slug":"potential-pitfalls-to-avoid-when-passing-around-async-lambdas","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/potential-pitfalls-to-avoid-when-passing-around-async-lambdas\/","title":{"rendered":"Potential pitfalls to avoid when passing around async lambdas"},"content":{"rendered":"<p>One of the really useful capabilities of the new async methods feature in C# and Visual Basic is the ability to write async lambdas and anonymous methods (from here on in this post, I&rsquo;ll refer to both of these as async lambdas, since the discussion applies equally to both).&nbsp; This allows you to easily get a delegate to represent an asynchronous operation, e.g.<\/p>\n<blockquote>\n<p><font size=\"2\" face=\"Consolas\"><font color=\"#4bacc6\">Func<\/font>&lt;<font color=\"#4bacc6\">Uri<\/font>,<font color=\"#4bacc6\">Task<\/font>&lt;<font color=\"#0000ff\">string<\/font>&gt;&gt; getContentsLowerCaseAsync = <font color=\"#0000ff\">async<\/font> url =&gt;        <br>{        <br>&nbsp;&nbsp;&nbsp; <font color=\"#0000ff\">string<\/font> contents = <font color=\"#0000ff\">await<\/font> DownloadString(url);        <br>&nbsp;&nbsp;&nbsp; <font color=\"#0000ff\">return<\/font> contents.ToLower();        <br>};<\/font><\/p>\n<\/blockquote>\n<p>Async methods in C# and Visual Basic can return void, Task, or Task&lt;TResult&gt;, which means they can be mapped to delegates that return void, Task, or Task&lt;TResult&gt;.&nbsp; This is very powerful, but it can also lead to subtle bugs if you&rsquo;re not careful.<\/p>\n<p>Most methods today that accept as a parameter a delegate that returns void (e.g. Action, Action&lt;T&gt;, etc.) expect the work of that delegate to be completed by the time the delegate completes.&nbsp; As a simple example, consider a timing helper function, whose job it is to time how long a particular piece of code takes to execute:<\/p>\n<blockquote>\n<p><font face=\"Consolas\"><font size=\"2\"><font color=\"#0000ff\">public static double<\/font> Time(<font color=\"#4bacc6\">Action<\/font> action, <font color=\"#0000ff\">int<\/font> iters=10)          <br>{          <br>&nbsp;&nbsp;&nbsp; <font color=\"#0000ff\">var<\/font> sw = <font color=\"#4bacc6\">Stopwatch<\/font>.StartNew();          <br>&nbsp;&nbsp;&nbsp; <font color=\"#0000ff\">for<\/font>(int i=0; i&lt;iters; i++) action();          <br>&nbsp;&nbsp;&nbsp; <font color=\"#0000ff\">return<\/font> sw.Elapsed.TotalSeconds \/ iters;          <br>}<\/font><\/font><\/p>\n<\/blockquote>\n<p>With this function, if I then run the following code:<\/p>\n<blockquote>\n<p><font face=\"Consolas\"><font size=\"2\"><font color=\"#0000ff\">static void<\/font> Main()          <br>{          <br>&nbsp;&nbsp;&nbsp; <font color=\"#0000ff\">double<\/font> secs = Time(() =&gt;          <br>&nbsp;&nbsp;&nbsp; {          <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color=\"#4bacc6\">Thread<\/font>.Sleep(1000);          <br>&nbsp;&nbsp;&nbsp; });          <br>&nbsp;&nbsp;&nbsp; <font color=\"#4bacc6\">Console<\/font>.WriteLine(&#8220;Seconds: {0:F7}&#8221;, secs);          <br>}<\/font><\/font><\/p>\n<\/blockquote>\n<p>I see this written out to the console:<\/p>\n<blockquote>\n<p><font size=\"2\" face=\"Consolas\">Seconds: 0.9999956       <br>Press any key to continue . . .<\/font><\/p>\n<\/blockquote>\n<p>That&rsquo;s what I&rsquo;d expect: we asked to sleep for one second, and that&rsquo;s almost exactly what the timing showed.&nbsp; But now consider an alternate piece of code:<\/p>\n<blockquote>\n<p><font face=\"Consolas\"><font size=\"2\"><font color=\"#0000ff\">static void<\/font> Main()          <br>{          <br>&nbsp;&nbsp;&nbsp; <font color=\"#0000ff\">double<\/font> secs = Time(<font color=\"#0000ff\">async<\/font> () =&gt;          <br>&nbsp;&nbsp;&nbsp; {          <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color=\"#0000ff\">await<\/font> <font color=\"#4bacc6\">Task<\/font>.Delay(1000);          <br>&nbsp;&nbsp;&nbsp; });          <br>&nbsp;&nbsp;&nbsp; <font color=\"#4bacc6\">Console<\/font>.WriteLine(<font color=\"#c0504d\">&#8220;Seconds: {0:F7}&#8221;<\/font>, secs);          <br>}<\/font><\/font><\/p>\n<\/blockquote>\n<p>When I run this, I see the following written out to the console:<\/p>\n<blockquote>\n<p><font size=\"2\" face=\"Consolas\">Seconds: 0.0000341       <br>Press any key to continue . . .<\/font><\/p>\n<\/blockquote>\n<p>Huh? Here we have an async method that&rsquo;s awaiting a Task that won&rsquo;t complete for a second, so this asynchronous method&rsquo;s execution should also be at least a second, and yet the timer is telling us that it took only 34 microseconds?&nbsp; What&rsquo;s going on?<\/p>\n<p>To understand this effect, we need to remember how async methods operate.&nbsp; When you invoke an async method, it starts running synchronously.&nbsp; If the method doesn&rsquo;t have any awaits in it, or if all of the awaits in the method are on awaitables that are already completed by the time they&rsquo;re awaited, then the method will run entirely synchronously.&nbsp; However, when the method encounters the first await that yields, the async method returns.&nbsp; In the case of an async method that returns a Task or a Task&lt;TResult&gt;, the method at this point returns the Task or Task&lt;TResult&gt; that represents the async method&rsquo;s execution, and the caller can use that task to wait synchronous (e.g. Wait()) or asynchronously (e.g. await, ContinueWith) for the method to asynchronously complete.&nbsp; In the case of a void method, though, no handle is handed back.&nbsp; Async void methods are thus often referred to as &ldquo;fire and forget.&rdquo;<\/p>\n<p>Now with that background, consider what&rsquo;s happening with our timing function.&nbsp; Our Time method accepts an Action, so the compiler is going to map our &ldquo;async () =&gt; { &hellip; }&rdquo; to being a void-returning async method, and the Action passed into the Time method will be for that void method.&nbsp; Thus, when Time invokes the Action, the Action will return as soon as it hits the first await that yields, which is our await for the delay task.&nbsp; This means that we&rsquo;re really only timing the invocation of the async method up until the await, but not including the time to await the task or what comes after it.<\/p>\n<p>We can fix this by modifying our Time function to accept a Func&lt;Task&gt; instead of an Action:<\/p>\n<blockquote>\n<p><font size=\"2\" face=\"Consolas\"><font color=\"#0000ff\">public static double<\/font> Time(<font color=\"#4bacc6\">Func<\/font>&lt;<font color=\"#4bacc6\">Task<\/font>&gt; func, <font color=\"#0000ff\">int<\/font> iters=10)        <br>{        <br>&nbsp;&nbsp;&nbsp; <font color=\"#0000ff\">var<\/font> sw = <font color=\"#4bacc6\">Stopwatch<\/font>.StartNew();        <br>&nbsp;&nbsp;&nbsp; <font color=\"#0000ff\">for<\/font> (<font color=\"#0000ff\">int<\/font> i = 0; i &lt; iters; i++) func().Wait();        <br>&nbsp;&nbsp;&nbsp; <font color=\"#0000ff\">return<\/font> sw.Elapsed.TotalSeconds \/ iters;        <br>}<\/font><\/p>\n<\/blockquote>\n<p>Now when I compile and run our async lambda, I get the following output that&rsquo;s what I&rsquo;d expect:<\/p>\n<blockquote>\n<p><font size=\"2\" face=\"Consolas\">Seconds: 1.0078671       <br>Press any key to continue . . .<\/font><\/p>\n<\/blockquote>\n<p>Void-returning methods aren&rsquo;t the only potentially problematic area; they&rsquo;re just the easiest example to highlight, because it&rsquo;s very clear from the signature that they don&rsquo;t return anything and thus are only useful for their side-effects, which means that code invoking them typically needs them to run to completion before making forward progress (since it likely depends on those side-effects having taken place), and async void methods defy that.<\/p>\n<p>A more complicated but still problematic example is a generic method that accepts an Action as a parameter and returns a Task, or that accepts a Func&lt;&hellip;,TResult&gt; as a parameter and returns a Task&lt;TResult&gt;, such as Task.Factory.StartNew.&nbsp; Consider the following:<\/p>\n<blockquote>\n<p><font size=\"2\" face=\"Consolas\"><font color=\"#0000ff\">var<\/font> t = <font color=\"#4bacc6\">Task<\/font>.Factory.StartNew(() =&gt;        <br>{        <br>&nbsp;&nbsp;&nbsp; <font color=\"#4bacc6\">Thread<\/font>.Sleep(1000);        <br>&nbsp;&nbsp;&nbsp; <font color=\"#0000ff\">return<\/font> 42;        <br>});<\/font><\/p>\n<\/blockquote>\n<p>Here StartNew accepts a delegate of type Func&lt;int&gt;, and returns a Task&lt;int&gt; representing the execution of the Func&lt;int&gt; delegate.&nbsp; Makes sense.&nbsp; But now consider the following:<\/p>\n<blockquote>\n<p><font size=\"2\" face=\"Consolas\"><font color=\"#0000ff\">var<\/font> t = <font color=\"#4bacc6\">Task<\/font>.Factory.StartNew(<font color=\"#0000ff\">async<\/font> () =&gt;        <br>{        <br><font color=\"#4bacc6\">&nbsp;&nbsp;&nbsp; <font color=\"#0000ff\">await <\/font>Task<\/font>.Delay(1000);        <br><font color=\"#0000ff\">&nbsp;&nbsp;&nbsp; return<\/font> 42;        <br>});<\/font><\/p>\n<\/blockquote>\n<p>Any guesses as to what the type of &lsquo;t&rsquo; is?&nbsp; StartNew accepts a Func&lt;TResult&gt; and returns a Task&lt;TResult&gt;.&nbsp; We&rsquo;re passing in an async lambda that will give back a Task&lt;int&gt;, which means the TResult in Func&lt;TResult&gt; is actually Task&lt;int&gt;, such that the delegate provided to StartNew is a Func&lt;Task&lt;int&gt;&gt;.&nbsp; That means that this call to StartNew is actually returning a Task&lt;Task&lt;int&gt;&gt;.&nbsp; The task created by StartNew will invoke the Func&lt;Task&lt;int&gt;&gt;, which will run synchronously until the first await that yields, at which point the Func&lt;Task&lt;int&gt;&gt; will return, handing back the result Task&lt;int&gt; that represents the async lambda&rsquo;s execution.&nbsp; StartNew will then complete the Task&lt;Task&lt;int&gt;&gt; that it handed back, since the delegate associated with that task has completed its synchronous execution.&nbsp; If I wrote code that depended on the returned task&rsquo;s completion to mean that the async lambda had completed, I&rsquo;d be sorely disappointed.&nbsp; It&rsquo;s actually the returned task&rsquo;s Result (which is itself a Task&lt;int&gt;) that represents the async lambda.<\/p>\n<p>There are a few ways to address this, such as using the Unwrap method:&nbsp; <\/p>\n<blockquote>\n<p><font size=\"2\" face=\"Consolas\"><font color=\"#0000ff\">var<\/font> t = <font color=\"#4bacc6\">Task<\/font>.Factory.StartNew(<font color=\"#0000ff\">async<\/font> () =&gt;        <br>{        <br><font color=\"#4bacc6\"><font color=\"#0000ff\">&nbsp;&nbsp;&nbsp; await <\/font>Task<\/font>.Delay(1000);        <br><font color=\"#0000ff\">&nbsp;&nbsp;&nbsp; return<\/font> 42;        <br>})<strong>.Unwrap()<\/strong>;<\/font><\/p>\n<\/blockquote>\n<p>For more information, see my previous blog post on this (and on how Task.Run differs in behavior here from Task.Factory.StartNew) at <a title=\"https:\/\/blogs.msdn.com\/b\/pfxteam\/archive\/2011\/10\/24\/10229468.aspx\" href=\"https:\/\/blogs.msdn.com\/b\/pfxteam\/archive\/2011\/10\/24\/10229468.aspx\">https:\/\/blogs.msdn.com\/b\/pfxteam\/archive\/2011\/10\/24\/10229468.aspx<\/a>.<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>One of the really useful capabilities of the new async methods feature in C# and Visual Basic is the ability to write async lambdas and anonymous methods (from here on in this post, I&rsquo;ll refer to both of these as async lambdas, since the discussion applies equally to both).&nbsp; This allows you to easily get [&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":[7925,36,7909,7912],"class_list":["post-56023","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-pfxteam","tag-net-4-5","tag-async","tag-parallel-extensions","tag-task-parallel-library"],"acf":[],"blog_post_summary":"<p>One of the really useful capabilities of the new async methods feature in C# and Visual Basic is the ability to write async lambdas and anonymous methods (from here on in this post, I&rsquo;ll refer to both of these as async lambdas, since the discussion applies equally to both).&nbsp; This allows you to easily get [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/56023","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=56023"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/56023\/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=56023"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=56023"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=56023"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}