{"id":683,"date":"2011-10-02T22:17:00","date_gmt":"2011-10-02T22:17:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/pfxteam\/2011\/10\/02\/keeping-async-methods-alive\/"},"modified":"2011-10-02T22:17:00","modified_gmt":"2011-10-02T22:17:00","slug":"keeping-async-methods-alive","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/keeping-async-methods-alive\/","title":{"rendered":"Keeping Async Methods Alive"},"content":{"rendered":"<p>Consider a type that will print out a message when it&rsquo;s finalized, and that has a Dispose method which will suppress finalization:<\/p>\n<blockquote>\n<p><span style=\"font-family: Consolas\">class DisplayOnFinalize : IDisposable <br>{ <br>&nbsp;&nbsp;&nbsp; public void Dispose() { GC.SuppressFinalize(this); } <br>&nbsp;&nbsp;&nbsp; ~DisplayOnFinalize() { Console.WriteLine(&ldquo;Finalized&rdquo;); } <br>}<\/span><\/p>\n<\/blockquote>\n<p>Now consider a simple usage of this class:<\/p>\n<blockquote>\n<p><span style=\"font-family: Consolas\">void Foo() <br>{ <br>&nbsp;&nbsp;&nbsp; <\/span>var tcs = new TaskCompletionSource&lt;bool&gt;(); <br><span style=\"font-family: Consolas\">&nbsp;&nbsp;&nbsp; using(new DisplayOnFinalize()) <br>&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tcs.Task.Wait(); <br>&nbsp;&nbsp;&nbsp; } <br>}<\/span><\/p>\n<\/blockquote>\n<p>This method instantiates an instance of the finalizable class, and then blocks waiting for a task to be completed prior to disposing of the DisplayOnFinalize instance.&nbsp; The task on which this code waits will <a href=\"https:\/\/blogs.msdn.com\/b\/pfxteam\/archive\/2011\/10\/02\/10218999.aspx\">never complete<\/a>, and thus the calling thread will remain blocked at this location.&nbsp; That thread&rsquo;s stack will maintain a reference to the DisplayOnFinalize class, since if the wait were to complete the thread would need to invoke that instance&rsquo;s Dispose method.&nbsp; And as such, the message will never be printed out.&nbsp;<\/p>\n<p>Now, consider a small variation:<\/p>\n<blockquote>\n<p><span style=\"font-family: Consolas\"><strong>async<\/strong> void Foo() <br>{ <br>&nbsp;&nbsp;&nbsp; var tcs = new TaskCompletionSource&lt;bool&gt;(); <br>&nbsp;&nbsp;&nbsp; using(new DisplayOnFinalize()) <br>&nbsp;&nbsp;&nbsp; {<\/span><span style=\"font-family: Consolas\"> <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <strong>await<\/strong> tcs.Task; <br>&nbsp;&nbsp;&nbsp; } <br>}<\/span><\/p>\n<\/blockquote>\n<p>The only differences here are that I&rsquo;ve added the async keyword to the signature of my method, and I&rsquo;m now asynchronously waiting for the task to complete (via the await keyword) rather than synchronously waiting for it to complete (via the Wait method).&nbsp; However, this has a significant effect on behavior.&nbsp; Of course, there&rsquo;s the important difference that you&rsquo;d expect, that we&rsquo;re asynchronously waiting for the task and thus we&rsquo;re not blocking the calling thread while waiting (forever) for the task to complete.&nbsp; However, there&rsquo;s a more subtle but nevertheless significant difference here&hellip; if you were to call this method repeatedly, you&rsquo;d start to see &ldquo;Finalized&rdquo; getting printed out as the DisplayOnFinalize instances got garbage collected and finalized.<\/p>\n<p>The async\/await keywords tell the C#\/Visual Basic compiler to rewrite your async method into a state machine, where the code that comes after the await is logically part of a continuation hooked up to the task (or, in general, the awaitable) being awaited.&nbsp; The following isn&rsquo;t exactly how the transformation happens, but you can think of the previous example as logically translating into something like the following (for the sake of this post, I&rsquo;m leaving out lots of otherwise important details):<\/p>\n<blockquote>\n<p><span style=\"font-family: Consolas\">void Foo() <br>{ <br>&nbsp;&nbsp;&nbsp; <\/span>var tcs = new TaskCompletionSource&lt;bool&gt;();<span style=\"font-family: Consolas\"> <br>&nbsp;&nbsp;&nbsp; var d = new DisplayOnFinalize();<br><strong>&nbsp;&nbsp;&nbsp; <\/strong>tcs.Task.ContinueWith(delegate <br>&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d.Dispose(); <br>&nbsp;&nbsp;&nbsp; });<\/span><span style=\"font-family: Consolas\"> <br>}<\/span><\/p>\n<\/blockquote>\n<p>The code that comes after the await is in effect hooked up as a continuation, and in this case that code is the code to dispose of the DisplayOnFinalize instance.&nbsp; Now, when the call to Foo returns, there&rsquo;s no more reference via the thread&rsquo;s stack to &lsquo;d&rsquo;.&nbsp; The only reference to &lsquo;d&rsquo; is in the closure\/delegate hooked up to the task as a continuation.&nbsp; If that task were rooted, that would be enough to keep the DisplayOnFinalize instance alive, but the task isn&rsquo;t rooted.&nbsp; The task is referred to by the TaskCompletionSource&lt;bool&gt; instance &lsquo;tcs&rsquo; on the thread&rsquo;s stack, but when the call to Foo goes away, so too does that reference to &lsquo;tcs&rsquo;.&nbsp; And thus, all of these instances become available for garbage collection.<\/p>\n<p>All of this serves to highlight an important fact: when you await something, it&rsquo;s that something which needs to keep the async method&rsquo;s execution alive via a reference to the continuation object that&rsquo;s provided by &lsquo;await&rsquo; to the awaited awaitable&rsquo;s awaiter (try saying that ten times fast).&nbsp; When you await Task.Run(&hellip;), the task you&rsquo;re awaiting is rooted in the ThreadPool&rsquo;s queues (or if the task is already executing, it&rsquo;s rooted by the stack processing the task).&nbsp; When you await Task.Delay(&hellip;), the task you&rsquo;re awaiting is rooted by the underlying timer&rsquo;s internal data structures.&nbsp; When you await a task for an async I\/O operation, the task is typically rooted by some data structure held by the I\/O completion port that will be signaled when the async operation completes.&nbsp; And so on.&nbsp;<\/p>\n<p>This all makes logical sense: in order to complete the task when the async operation completes, the thing that will be completing it must have a reference to it.&nbsp; But it&rsquo;s still something good to keep in mind&hellip; if you ever find that your async methods aren&rsquo;t running to completion, consider whether awaitables you&rsquo;re awaiting might be getting garbage collected before they complete.&nbsp; In my <a href=\"https:\/\/blogs.msdn.com\/b\/pfxteam\/archive\/2011\/10\/02\/10218999.aspx\">previous post<\/a>, I referred to a real bug that was discovered to be caused by a task never completing.&nbsp; The way we happened across that bug was because a finalizable class similar in nature to the one shown previously was actually in use, and its finalizer was firing.&nbsp; This led us to realize that it was invoked because the awaited task was getting garbage collected before it was completed, which was because of a a queue of work referencing completion sources, and that queue that was being cleared without canceling those associated tasks.<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Consider a type that will print out a message when it&rsquo;s finalized, and that has a Dispose method which will suppress finalization: class DisplayOnFinalize : IDisposable { &nbsp;&nbsp;&nbsp; public void Dispose() { GC.SuppressFinalize(this); } &nbsp;&nbsp;&nbsp; ~DisplayOnFinalize() { Console.WriteLine(&ldquo;Finalized&rdquo;); } } Now consider a simple usage of this class: void Foo() { &nbsp;&nbsp;&nbsp; var tcs = [&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,322,7909,7912],"class_list":["post-683","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-pfxteam","tag-net-4-5","tag-async","tag-debugging","tag-parallel-extensions","tag-task-parallel-library"],"acf":[],"blog_post_summary":"<p>Consider a type that will print out a message when it&rsquo;s finalized, and that has a Dispose method which will suppress finalization: class DisplayOnFinalize : IDisposable { &nbsp;&nbsp;&nbsp; public void Dispose() { GC.SuppressFinalize(this); } &nbsp;&nbsp;&nbsp; ~DisplayOnFinalize() { Console.WriteLine(&ldquo;Finalized&rdquo;); } } Now consider a simple usage of this class: void Foo() { &nbsp;&nbsp;&nbsp; var tcs = [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/683","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=683"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/683\/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=683"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=683"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=683"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}