<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://msmvps.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Jon Skeet: Coding Blog : Evil Code, C# 5</title><link>http://msmvps.com/blogs/jon_skeet/archive/tags/Evil+Code/C_2300_+5/default.aspx</link><description>Tags: Evil Code, C# 5</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP2 (Build: 40407.4157)</generator><item><title>Eduasync part 15: implementing COMEFROM with a horrible hack</title><link>http://msmvps.com/blogs/jon_skeet/archive/2011/11/11/eduasync-part-15-implementing-comefrom-with-a-horrible-hack.aspx</link><pubDate>Fri, 11 Nov 2011 22:15:11 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1802363</guid><dc:creator>skeet</dc:creator><slash:comments>6</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/rsscomments.aspx?PostID=1802363</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/commentapi.aspx?PostID=1802363</wfw:comment><comments>http://msmvps.com/blogs/jon_skeet/archive/2011/11/11/eduasync-part-15-implementing-comefrom-with-a-horrible-hack.aspx#comments</comments><description>&lt;p&gt;Ages ago when I wrote my &lt;a href="http://msmvps.com/blogs/jon_skeet/archive/2011/06/29/eduasync-part-14-data-passing-in-coroutines.aspx"&gt;previous Eduasync post&lt;/a&gt;, I said we&amp;#39;d look at a pipeline model of coroutines. I&amp;#39;ve decided to skip that, as I &lt;em&gt;do&lt;/em&gt; want to cover the topic of this post, and I&amp;#39;ve got some more &amp;quot;normal&amp;quot; async ideas to write about too. If you want to look at the pipeline coroutines code, it&amp;#39;s &lt;a href="http://code.google.com/p/eduasync/source/browse/#hg%2Fsrc%2FPipelineCoroutines"&gt;project 20&lt;/a&gt; in the source repository. Have fun, and don&amp;#39;t blame me if you get confused reading it - so do I.&lt;/p&gt;  &lt;p&gt;The code I &lt;em&gt;am&lt;/em&gt; going to write about is horrible too. It&amp;#39;s almost as tricky to understand, and it does &lt;em&gt;far&lt;/em&gt; nastier things. Things that the C# 5 specification explicitly says you shouldn&amp;#39;t do.&lt;/p&gt;  &lt;p&gt;If it makes you feel any better when your head hurts reading this code, spare a thought for me - I haven&amp;#39;t looked at it in over six months, and &lt;em&gt;I&lt;/em&gt; don&amp;#39;t have a blog post explaining how it&amp;#39;s meant to work. I just have almost entirely uncommented code which is &lt;em&gt;designed&lt;/em&gt; to be hard to understand (in terms of the main program flow).&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;On no account should any code like this ever be used for anything remotely serious.&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;With that health warning out of the way, let&amp;#39;s have a look at it...&lt;/p&gt;  &lt;h3&gt;COMEFROM at the caller level&lt;/h3&gt;  &lt;p&gt;The idea is to implement the &lt;a href="http://en.wikipedia.org/wiki/COMEFROM"&gt;COMEFROM&lt;/a&gt; control structure, which is sort of the opposite of GOTO (or in my implementation, more of a GOSUB). There are two operations, effectively:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;ComeFrom(label): Register interest in a particular label. &lt;/li&gt;    &lt;li&gt;Label(label): If anyone has registered interested in the given label, keep going from their registration point (which will be within a method), then continue from where we left off afterwards. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;In some senses it&amp;#39;s a little like the observer pattern, with labels taking the place of events. However, it looks entirely different and is &lt;em&gt;much&lt;/em&gt; harder to get your head round, because instead of having a nicely-encapsulated action which is subscribed to an event, we just have a ComeFrom call which lets us jump back into a method somewhat arbitrarily.&lt;/p&gt;  &lt;p&gt;I have two implementations, in &lt;a href="http://code.google.com/p/eduasync/source/browse/#hg%2Fsrc%2FComeFromCoroutines"&gt;project 22&lt;/a&gt; and &lt;a href="http://code.google.com/p/eduasync/source/browse/#hg%2Fsrc%2FStateSavingComeFrom"&gt;project 23&lt;/a&gt; in source control. Project 22 is almost sane; a little funky, but not too bad. Project 23 is where the fun really happens. In addition to the operations listed above, there&amp;#39;s an Execute operation which is sort of an implementation detail - it allows an async method containing ComeFrom calls to be executed without returning earlier than we might want.&lt;/p&gt;  &lt;p&gt;Let&amp;#39;s look at some code and the output, and try to work out what&amp;#39;s going on.&lt;/p&gt;  &lt;div class="code"&gt;&lt;span class="Modifier"&gt;internal&lt;/span&gt;&amp;#160;&lt;span class="ReferenceType"&gt;class&lt;/span&gt; Program     &lt;br /&gt;{     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;private&lt;/span&gt;&amp;#160;&lt;span class="Modifier"&gt;static&lt;/span&gt;&amp;#160;&lt;span class="ValueType"&gt;void&lt;/span&gt; Main(&lt;span class="ReferenceType"&gt;string&lt;/span&gt;[] args)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Coordinator coordinator = &lt;span class="Keyword"&gt;new&lt;/span&gt; Coordinator(SimpleEntryPoint);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; coordinator.Start();     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;private&lt;/span&gt;&amp;#160;&lt;span class="Modifier"&gt;static&lt;/span&gt;&amp;#160;&lt;span class="Modifier"&gt;async&lt;/span&gt;&amp;#160;&lt;span class="ValueType"&gt;void&lt;/span&gt; SimpleEntryPoint(Coordinator coordinator)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;await&lt;/span&gt; coordinator.Execute(SimpleOtherMethod);     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Console.WriteLine(&lt;span class="String"&gt;&amp;quot;First call to Label(x)&amp;quot;&lt;/span&gt;);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;await&lt;/span&gt; coordinator.Label(&lt;span class="String"&gt;&amp;quot;x&amp;quot;&lt;/span&gt;);     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Console.WriteLine(&lt;span class="String"&gt;&amp;quot;Second call to Label(x)&amp;quot;&lt;/span&gt;);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;await&lt;/span&gt; coordinator.Label(&lt;span class="String"&gt;&amp;quot;x&amp;quot;&lt;/span&gt;);     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Console.WriteLine(&lt;span class="String"&gt;&amp;quot;Registering interesting in y&amp;quot;&lt;/span&gt;);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="ValueType"&gt;bool&lt;/span&gt; firstTime = &lt;span class="Keyword"&gt;true&lt;/span&gt;;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;await&lt;/span&gt; coordinator.ComeFrom(&lt;span class="String"&gt;&amp;quot;y&amp;quot;&lt;/span&gt;);     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Console.WriteLine(&lt;span class="String"&gt;&amp;quot;After ComeFrom(y). FirstTime={0}&amp;quot;&lt;/span&gt;, firstTime);     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Statement"&gt;if&lt;/span&gt; (firstTime)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; firstTime = &lt;span class="Keyword"&gt;false&lt;/span&gt;;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;await&lt;/span&gt; coordinator.Label(&lt;span class="String"&gt;&amp;quot;y&amp;quot;&lt;/span&gt;);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Console.WriteLine(&lt;span class="String"&gt;&amp;quot;Finished&amp;quot;&lt;/span&gt;);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;private&lt;/span&gt;&amp;#160;&lt;span class="Modifier"&gt;static&lt;/span&gt;&amp;#160;&lt;span class="Modifier"&gt;async&lt;/span&gt;&amp;#160;&lt;span class="ValueType"&gt;void&lt;/span&gt; SimpleOtherMethod(Coordinator coordinator)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Console.WriteLine(&lt;span class="String"&gt;&amp;quot;Start of SimpleOtherMethod&amp;quot;&lt;/span&gt;);     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="ValueType"&gt;int&lt;/span&gt; count = 0;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;await&lt;/span&gt; coordinator.ComeFrom(&lt;span class="String"&gt;&amp;quot;x&amp;quot;&lt;/span&gt;);     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Console.WriteLine(&lt;span class="String"&gt;&amp;quot;After ComeFrom x in SimpleOtherMethod. count={0}. Returning.&amp;quot;&lt;/span&gt;,     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; count);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; count++;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }     &lt;br /&gt;}&lt;/div&gt;  &lt;p&gt;The reason for the &amp;quot;Simple&amp;quot; prefix on the method names is that there&amp;#39;s another example in the same file, with a more complex control flow.&lt;/p&gt;  &lt;p&gt;Here&amp;#39;s the output - then we can look at why we&amp;#39;re getting it...&lt;/p&gt;  &lt;div class="output"&gt;Start of SimpleOtherMethod    &lt;br /&gt;After ComeFrom x in SimpleOtherMethod. count=0. Returning.     &lt;br /&gt;First call to Label(x)     &lt;br /&gt;After ComeFrom x in SimpleOtherMethod. count=1. Returning.     &lt;br /&gt;Second call to Label(x)     &lt;br /&gt;After ComeFrom x in SimpleOtherMethod. count=2. Returning.     &lt;br /&gt;Registering interesting in y     &lt;br /&gt;After ComeFrom(y). FirstTime=True     &lt;br /&gt;After ComeFrom(y). FirstTime=False     &lt;br /&gt;Finished &lt;/div&gt;  &lt;p&gt;So, the control flow is a bit like this:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Start SimpleEntryPoint      &lt;ul&gt;       &lt;li&gt;Call into SimpleOtherMethod          &lt;ul&gt;           &lt;li&gt;Log &amp;quot;Start of SimpleOtherMethod&amp;quot; &lt;/li&gt;            &lt;li&gt;Initialize the &amp;quot;count&amp;quot; variable with value 0 &lt;/li&gt;            &lt;li&gt;Register interest in x; ComeFrom remembers the continuation &lt;em&gt;but keeps going&lt;/em&gt;. &lt;/li&gt;            &lt;li&gt;Log &amp;quot;After ComeFrom x in SimpleOtherMethod. count=0. Returning.&amp;quot; &lt;/li&gt;            &lt;li&gt;Increment count to 1. &lt;/li&gt;            &lt;li&gt;Return. &lt;/li&gt;         &lt;/ul&gt;       &lt;/li&gt;        &lt;li&gt;Return takes us back to SimpleEntryPoint... &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;Log &amp;quot;First call to Label(x)&amp;quot; &lt;/li&gt;    &lt;li&gt;Call Label(&amp;quot;x&amp;quot;)...      &lt;ul&gt;       &lt;li&gt;... which takes us back into SimpleOtherMethod (remember, the method we thought we&amp;#39;d finished executing?) just after ComeFrom          &lt;ul&gt;           &lt;li&gt;Log AfterComeFrom x in SimpleOtherMethod. count=1. Returning. &lt;/li&gt;            &lt;li&gt;Increment count to 2. &lt;/li&gt;            &lt;li&gt;Return. &lt;/li&gt;         &lt;/ul&gt;       &lt;/li&gt;        &lt;li&gt;Return takes us back to SimpleEntryPoint... &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;Log &amp;quot;Second call to Label(x)&amp;quot; &lt;/li&gt;    &lt;li&gt;Call Label(&amp;quot;x&amp;quot;)...      &lt;ul&gt;       &lt;li&gt;... which takes us back into SimpleOtherMethod again          &lt;ul&gt;           &lt;li&gt;Log AfterComeFrom x in SimpleOtherMethod. count=2. Returning. &lt;/li&gt;            &lt;li&gt;Increment count to 3. &lt;/li&gt;            &lt;li&gt;Return. &lt;/li&gt;         &lt;/ul&gt;       &lt;/li&gt;        &lt;li&gt;Return takes us back to SimpleEntryPoint... &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;Log &amp;quot;Registering interest in y&amp;quot; &lt;/li&gt;    &lt;li&gt;Initialize the &amp;quot;firstTime&amp;quot; variable with value true. &lt;/li&gt;    &lt;li&gt;Register interest in y; ComeFrom remembers the continuation and keeps going &lt;/li&gt;    &lt;li&gt;Log &amp;quot;After ComeFrom(y). FirstTime=True&amp;quot; &lt;/li&gt;    &lt;li&gt;Check the value of firstTime... It&amp;#39;s true, so:      &lt;ul&gt;       &lt;li&gt;Set firstTime to false &lt;/li&gt;        &lt;li&gt;Call Label(&amp;quot;y&amp;quot;) &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;... which takes us back to earlier in the method (just after ComeFrom), like a normal looping construct... &lt;/li&gt;    &lt;li&gt;Log &amp;quot;After ComeFrom(y). FirstTime=False&amp;quot; &lt;/li&gt;    &lt;li&gt;Check the value of firstTime... It&amp;#39;s false, so:      &lt;ul&gt;       &lt;li&gt;Log &amp;quot;Finished&amp;quot; &lt;/li&gt;        &lt;li&gt;Exit! &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Doing all of this has a few interesting challenges. Let&amp;#39;s look at them one at a time... and I would &lt;em&gt;strongly&lt;/em&gt; advise you not to try to pay too much attention to the details.&lt;/p&gt;  &lt;h3&gt;Noting a continuation and continuing regardless...&lt;/h3&gt;  &lt;p&gt;Just as a quick reminder before we get cracking, it&amp;#39;s worth remembering that &lt;em&gt;all&lt;/em&gt; of this is entirely synchronous, despite being implemented with async. There&amp;#39;s only a single user thread involved here. As with previous parts, we maintain a stack of actions to call, and basically keep calling from the top until we&amp;#39;re done - but the actions we call can create extra stack entries, of course.&lt;/p&gt;  &lt;p&gt;ComeFrom has unusual semantics in terms of async. We want to remember the continuation &lt;em&gt;and&lt;/em&gt; keep executing as if we didn&amp;#39;t need to wait. We can easily do one side or the other. If we wanted to just keep going without needing to know about the continuation, we could just return true from IsCompleted. If we just want to remember the continuation, we can make the awaiter&amp;#39;s IsCompleted property return false, and remember the continuation when it&amp;#39;s passed to OnCompleted. How do we do both?&lt;/p&gt;  &lt;p&gt;Well, effectively we want to remember the continuation and then call it immediately. But we can&amp;#39;t &lt;em&gt;just&lt;/em&gt; call it directly from OnCompleted, as otherwise each ComeFrom call would end up in a &amp;quot;real&amp;quot; execution stack from, whereas our execution stack is stored as a Stack&amp;lt;Action&amp;gt;. So instead, we need to remember the continuation and immediately put it at the top of the stack.&lt;/p&gt;  &lt;p&gt;However, that only works if as soon as the generated code returns from the async method containing the ComeFrom call, we go back into the state machine. If we&amp;#39;d just called SimpleOtherMethod directly in SimpleEntryPoint, we would have continued within SimpleEntryPoint with the new stack entry just waiting around. This is why we need the Executor method: that does exactly the same thing, effectively shuffling the stack around. When it&amp;#39;s given something to execute, it puts its own continuation on the action stack, &lt;em&gt;then&lt;/em&gt; the action it&amp;#39;s been asked to execute, then returns. The top level code will then pick up the original action, and we&amp;#39;re away.&lt;/p&gt;  &lt;p&gt;So, here&amp;#39;s the code for Execute, which is the simplest part of the coordinator:&lt;/p&gt;  &lt;div class="code"&gt;&lt;span class="Modifier"&gt;public&lt;/span&gt; ExecuteAwaiter Execute(Action&amp;lt;Coordinator&amp;gt; action)     &lt;br /&gt;{     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Statement"&gt;return&lt;/span&gt;&amp;#160;&lt;span class="Keyword"&gt;new&lt;/span&gt; ExecuteAwaiter(() =&amp;gt; action(&lt;span class="Keyword"&gt;this&lt;/span&gt;), &lt;span class="Keyword"&gt;this&lt;/span&gt;);     &lt;br /&gt;}     &lt;br /&gt;    &lt;br /&gt;&lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;#160;&lt;span class="ReferenceType"&gt;class&lt;/span&gt; ExecuteAwaiter     &lt;br /&gt;{     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;private&lt;/span&gt;&amp;#160;&lt;span class="Modifier"&gt;readonly&lt;/span&gt; Action action;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;private&lt;/span&gt;&amp;#160;&lt;span class="Modifier"&gt;readonly&lt;/span&gt; Coordinator coordinator;     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;internal&lt;/span&gt; ExecuteAwaiter(Action action, Coordinator coordinator)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Keyword"&gt;this&lt;/span&gt;.action = action;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Keyword"&gt;this&lt;/span&gt;.coordinator = coordinator;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;public&lt;/span&gt; ExecuteAwaiter GetAwaiter()     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Statement"&gt;return&lt;/span&gt;&amp;#160;&lt;span class="Keyword"&gt;this&lt;/span&gt;;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="InlineComment"&gt;// Always yield&lt;/span&gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;#160;&lt;span class="ValueType"&gt;bool&lt;/span&gt; IsCompleted { get { &lt;span class="Statement"&gt;return&lt;/span&gt;&amp;#160;&lt;span class="Keyword"&gt;false&lt;/span&gt;; } }     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;#160;&lt;span class="ValueType"&gt;void&lt;/span&gt; OnCompleted(Action callerContinuation)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="InlineComment"&gt;// We want to execute the action continuation, then get back here,&lt;/span&gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="InlineComment"&gt;// allowing any extra continuations put on the stack *within* the action&lt;/span&gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="InlineComment"&gt;// to be executed.&lt;/span&gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; coordinator.stack.Push(callerContinuation);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; coordinator.stack.Push(action);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;#160;&lt;span class="ValueType"&gt;void&lt;/span&gt; GetResult()     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }     &lt;br /&gt;} &lt;/div&gt;  &lt;p&gt;All the awaitables in this project return themselves as the awaiter - when you don&amp;#39;t need any other state, it&amp;#39;s an easy step to take.&lt;/p&gt;  &lt;p&gt;That&amp;#39;s all we need to say about Execute, but how exactly are we capturing the continuation in ComeFrom?&lt;/p&gt;  &lt;h3&gt;Capturing continuations&lt;/h3&gt;  &lt;p&gt;Once we&amp;#39;ve got the action stack shuffling under our belts, there are two more problems with ComeFrom:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;What happens if we ComeFrom the same label twice? &lt;/li&gt;    &lt;li&gt;How do we really capture a continuation? &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The first point didn&amp;#39;t come up in the sample I&amp;#39;ve shown here, but it &lt;em&gt;does&lt;/em&gt; come up in the more complex example - imagine if SimpleOtherMethod had two ComeFrom calls; when we jump back to the first one, we&amp;#39;ll execute the second one again. I made a simple policy decision to only allow a single &amp;quot;return point&amp;quot; for any label - if a ComeFrom call tries to register the &lt;em&gt;existing &lt;/em&gt;continuation point for a label, we ignore it; otherwise we throw an exception. So we only need to care about a single continuation for any label, which makes life easier.&lt;/p&gt;  &lt;p&gt;The second point is trickier. If you remember back to earlier posts in this series, we saw that the state machine generated for async only really contains a single entry point (MoveNext) which is used for &lt;em&gt;all&lt;/em&gt; continuations. A variable in the state machine is responsible for remembering where we were within it between calls. So in order to really make the continuation remember the point at which it needs to continue, we need to remember that state. We need to store an object for the continuation, which contains the delegate to invoke, and the state of the state machine when we were first passed the continuation. I&amp;#39;ve created a class for this, unimaginatively called Continuation, which looks like this:&lt;/p&gt;  &lt;div class="code"&gt;&lt;span class="XmlComment"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;     &lt;br /&gt;&lt;span class="XmlComment"&gt;/// This hack allows a continuation to be executed more than once,&lt;/span&gt;     &lt;br /&gt;&lt;span class="XmlComment"&gt;/// contrary to the C# spec. It does this using reflection to store the&lt;/span&gt;     &lt;br /&gt;&lt;span class="XmlComment"&gt;/// value of the &amp;quot;state&amp;quot; field within the generated class. NEVER, EVER, EVER&lt;/span&gt;     &lt;br /&gt;&lt;span class="XmlComment"&gt;/// try to use this in real code. It&amp;#39;s purely for fun.&lt;/span&gt;     &lt;br /&gt;&lt;span class="XmlComment"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;     &lt;br /&gt;&lt;span class="Modifier"&gt;internal&lt;/span&gt;&amp;#160;&lt;span class="Modifier"&gt;sealed&lt;/span&gt;&amp;#160;&lt;span class="ReferenceType"&gt;class&lt;/span&gt; Continuation : IEquatable&amp;lt;Continuation&amp;gt;     &lt;br /&gt;{     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;private&lt;/span&gt;&amp;#160;&lt;span class="Modifier"&gt;readonly&lt;/span&gt;&amp;#160;&lt;span class="ValueType"&gt;int&lt;/span&gt; savedState;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;private&lt;/span&gt;&amp;#160;&lt;span class="Modifier"&gt;readonly&lt;/span&gt;&amp;#160;&lt;span class="ReferenceType"&gt;object&lt;/span&gt; target;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;private&lt;/span&gt;&amp;#160;&lt;span class="Modifier"&gt;readonly&lt;/span&gt; FieldInfo field;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;private&lt;/span&gt;&amp;#160;&lt;span class="Modifier"&gt;readonly&lt;/span&gt; Action action;     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;internal&lt;/span&gt; Continuation(Action action)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; target = action.Target;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; field = target.GetType().GetField(&lt;span class="String"&gt;&amp;quot;&amp;lt;&amp;gt;1__state&amp;quot;&lt;/span&gt;, BindingFlags.Instance | BindingFlags.NonPublic);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; savedState = (&lt;span class="ValueType"&gt;int&lt;/span&gt;) field.GetValue(target);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Keyword"&gt;this&lt;/span&gt;.action = action;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;internal&lt;/span&gt;&amp;#160;&lt;span class="ValueType"&gt;void&lt;/span&gt; Execute()     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; field.SetValue(target, savedState);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; action();     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="InlineComment"&gt;// Snip Equals/GetHashCode&lt;/span&gt;     &lt;br /&gt;} &lt;/div&gt;  &lt;p&gt;Yes, we use reflection to fish out the &amp;lt;&amp;gt;1__state variable initially, and poke the state machine with the same value when we next want to execute the continuation. All highly implementation-specific, of course.&lt;/p&gt;  &lt;p&gt;Now the ComeFrom method is reasonably straightforward - all we need is a dictionary mapping labels to continuations. Oh, and the same action stack shuffling as for Execute:&lt;/p&gt;  &lt;div class="code"&gt;&lt;span class="InlineComment"&gt;// In the coordinator&lt;/span&gt;     &lt;br /&gt;&lt;span class="Modifier"&gt;private&lt;/span&gt;&amp;#160;&lt;span class="Modifier"&gt;readonly&lt;/span&gt; Dictionary&amp;lt;&lt;span class="ReferenceType"&gt;string&lt;/span&gt;, Continuation&amp;gt; labels = &lt;span class="Keyword"&gt;new&lt;/span&gt; Dictionary&amp;lt;&lt;span class="ReferenceType"&gt;string&lt;/span&gt;, Continuation&amp;gt;();     &lt;br /&gt;    &lt;br /&gt;&lt;span class="Modifier"&gt;public&lt;/span&gt; ComeFromAwaiter ComeFrom(&lt;span class="ReferenceType"&gt;string&lt;/span&gt; label)     &lt;br /&gt;{     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Statement"&gt;return&lt;/span&gt;&amp;#160;&lt;span class="Keyword"&gt;new&lt;/span&gt; ComeFromAwaiter(label, &lt;span class="Keyword"&gt;this&lt;/span&gt;);     &lt;br /&gt;}     &lt;br /&gt;    &lt;br /&gt;&lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;#160;&lt;span class="ValueType"&gt;struct&lt;/span&gt; ComeFromAwaiter     &lt;br /&gt;{     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;private&lt;/span&gt;&amp;#160;&lt;span class="Modifier"&gt;readonly&lt;/span&gt;&amp;#160;&lt;span class="ReferenceType"&gt;string&lt;/span&gt; label;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;private&lt;/span&gt;&amp;#160;&lt;span class="Modifier"&gt;readonly&lt;/span&gt; Coordinator coordinator;     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;internal&lt;/span&gt; ComeFromAwaiter(&lt;span class="ReferenceType"&gt;string&lt;/span&gt; label, Coordinator coordinator)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Keyword"&gt;this&lt;/span&gt;.label = label;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Keyword"&gt;this&lt;/span&gt;.coordinator = coordinator;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;public&lt;/span&gt; ComeFromAwaiter GetAwaiter()     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Statement"&gt;return&lt;/span&gt;&amp;#160;&lt;span class="Keyword"&gt;this&lt;/span&gt;;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="InlineComment"&gt;// We *always* want to be given the continuation&lt;/span&gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;#160;&lt;span class="ValueType"&gt;bool&lt;/span&gt; IsCompleted { get { &lt;span class="Statement"&gt;return&lt;/span&gt;&amp;#160;&lt;span class="Keyword"&gt;false&lt;/span&gt;; } }     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;#160;&lt;span class="ValueType"&gt;void&lt;/span&gt; OnCompleted(Action action)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Continuation newContinuation = &lt;span class="Keyword"&gt;new&lt;/span&gt; Continuation(action);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Continuation oldContinuation;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Statement"&gt;if&lt;/span&gt; (!coordinator.labels.TryGetValue(label, &lt;span class="MethodParameter"&gt;out&lt;/span&gt; oldContinuation))     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="InlineComment"&gt;// First time coming from this label. Always succeeds.&lt;/span&gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; coordinator.labels[label] = newContinuation;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Statement"&gt;else&lt;/span&gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="InlineComment"&gt;// Current semantics are to prohibit two different ComeFrom calls for the same label.&lt;/span&gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="InlineComment"&gt;// An alternative would be to just replace the existing continuation with the new one,&lt;/span&gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="InlineComment"&gt;// in which case we wouldn&amp;#39;t need any of this - we could just use&lt;/span&gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="InlineComment"&gt;// coordinator.labels[label] = newContinuation;&lt;/span&gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="InlineComment"&gt;// unconditionally.&lt;/span&gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Statement"&gt;if&lt;/span&gt; (!oldContinuation.Equals(newContinuation))     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Statement"&gt;throw&lt;/span&gt;&amp;#160;&lt;span class="Keyword"&gt;new&lt;/span&gt; InvalidOperationException(&lt;span class="String"&gt;&amp;quot;Additional continuation detected for label &amp;quot;&lt;/span&gt; + label);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="InlineComment"&gt;// Okay, we&amp;#39;ve seen this one before. Nothing to see here, move on.&lt;/span&gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="InlineComment"&gt;// We actually want to continue from where we were: we&amp;#39;re only really marking the&lt;/span&gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="InlineComment"&gt;// ComeFrom point.&lt;/span&gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; coordinator.stack.Push(action);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;#160;&lt;span class="ValueType"&gt;void&lt;/span&gt; GetResult()     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }     &lt;br /&gt;} &lt;/div&gt;  &lt;p&gt;There&amp;#39;s one interesting point here which is somewhat subtle, and screwed me up for a bit...&lt;/p&gt;  &lt;h3&gt;The default value of a struct is always valid...&lt;/h3&gt;  &lt;p&gt;You may have noticed that ComeFromAwaiter is a struct. That&amp;#39;s pretty unusual for me. However, it&amp;#39;s also &lt;em&gt;absolutely critical&lt;/em&gt;. Without it, we&amp;#39;d get a NullReferenceException when we execute the continuation the second time.&lt;/p&gt;  &lt;p&gt;Normally, the flow of async methods looks a bit like this, for an await expression taking the &amp;quot;long&amp;quot; route (i.e. IsCompleted is false):&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Call GetAwaiter() and assign the result to an awaiter field &lt;/li&gt;    &lt;li&gt;Call IsCompleted (which returns false in this scenario) &lt;/li&gt;    &lt;li&gt;Set the state variable to remember where we&amp;#39;d got to &lt;/li&gt;    &lt;li&gt;Call OnCompleted &lt;/li&gt;    &lt;li&gt;Return &lt;/li&gt;    &lt;li&gt;... When we continue... &lt;/li&gt;    &lt;li&gt;Set state to 0 (running) &lt;/li&gt;    &lt;li&gt;Call GetResult() on the awaiter &lt;/li&gt;    &lt;li&gt;Set the awaiter field to default(&lt;em&gt;TypeOfAwaiter&lt;/em&gt;) &lt;/li&gt;    &lt;li&gt;Continue &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Now that&amp;#39;s fine when we&amp;#39;re only continuing &lt;em&gt;once&lt;/em&gt; - but if we need to jump into the middle of that sequence a second time, we&amp;#39;re going to call GetAwaiter() on the awaiter field &lt;em&gt;after it&amp;#39;s been set to the default value of the awaiter type&lt;/em&gt;. If the default value is null, we&amp;#39;ll go bang. So we &lt;em&gt;must&lt;/em&gt; use a struct.&lt;/p&gt;  &lt;p&gt;Fortunately, our GetResult() call doesn&amp;#39;t need any of the state in the awaiter - it&amp;#39;s &lt;em&gt;purely&lt;/em&gt; there to satisfy the normal flow of things. So we&amp;#39;re quite happy with a &amp;quot;default&amp;quot; ComeFrom awaiter.&lt;/p&gt;  &lt;h3&gt;Finally, labels...&lt;/h3&gt;  &lt;p&gt;We&amp;#39;ve now done all the hard work. The final piece of the puzzle is Label, which &lt;em&gt;just&lt;/em&gt; needs to check whether there&amp;#39;s a continuation to jump to, and shuffle the action stack in the way we&amp;#39;re now painfully accustomed to:&lt;/p&gt;  &lt;div class="code"&gt;&lt;span class="Modifier"&gt;public&lt;/span&gt; LabelAwaiter Label(&lt;span class="ReferenceType"&gt;string&lt;/span&gt; label)    &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Continuation continuation;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; labels.TryGetValue(label, &lt;span class="MethodParameter"&gt;out&lt;/span&gt; continuation);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Statement"&gt;return&lt;/span&gt;&amp;#160;&lt;span class="Keyword"&gt;new&lt;/span&gt; LabelAwaiter(continuation, &lt;span class="Keyword"&gt;this&lt;/span&gt;);    &lt;br /&gt;}    &lt;br /&gt;    &lt;br /&gt;&lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;#160;&lt;span class="ReferenceType"&gt;class&lt;/span&gt; LabelAwaiter    &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;private&lt;/span&gt;&amp;#160;&lt;span class="Modifier"&gt;readonly&lt;/span&gt; Continuation continuation;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;private&lt;/span&gt;&amp;#160;&lt;span class="Modifier"&gt;readonly&lt;/span&gt; Coordinator coordinator;    &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;internal&lt;/span&gt; LabelAwaiter(Continuation continuation, Coordinator coordinator)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Keyword"&gt;this&lt;/span&gt;.continuation = continuation;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Keyword"&gt;this&lt;/span&gt;.coordinator = coordinator;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;public&lt;/span&gt; LabelAwaiter GetAwaiter()    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Statement"&gt;return&lt;/span&gt;&amp;#160;&lt;span class="Keyword"&gt;this&lt;/span&gt;;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="InlineComment"&gt;// If there&amp;#39;s no continuation to execute, just breeze through.&lt;/span&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;#160;&lt;span class="ValueType"&gt;bool&lt;/span&gt; IsCompleted { get { &lt;span class="Statement"&gt;return&lt;/span&gt; continuation == &lt;span class="Keyword"&gt;null&lt;/span&gt;; } }    &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;#160;&lt;span class="ValueType"&gt;void&lt;/span&gt; OnCompleted(Action action)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="InlineComment"&gt;// We want to execute the ComeFrom continuation, then get back here.&lt;/span&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; coordinator.stack.Push(action);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; coordinator.stack.Push(continuation.Execute);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;#160;&lt;span class="ValueType"&gt;void&lt;/span&gt; GetResult()    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;} &lt;/div&gt;  &lt;p&gt;Almost painfully simple, really.&lt;/p&gt;  &lt;p&gt;So that &lt;em&gt;looks&lt;/em&gt; like all the code that&amp;#39;s used, right? Not &lt;em&gt;quite&lt;/em&gt;...&lt;/p&gt;  &lt;h3&gt;Reusable builders?&lt;/h3&gt;  &lt;p&gt;As we saw in the sample code, we can end up finishing the same async method multiple times (SimpleOtherMethod completes three times). That&amp;#39;s going to call SetResult on the AsyncVoidMethodBuilder three times... which feels like it &lt;em&gt;should&lt;/em&gt; go bang. Indeed, when I revisited my code earlier I wondered why it &lt;em&gt;didn&amp;#39;t&lt;/em&gt; go bang - it&amp;#39;s the sort of illegal state transition the framework is usually pretty good at picking up on.&lt;/p&gt;  &lt;p&gt;Then I remembered - this isn&amp;#39;t the framework&amp;#39;s AsyncVoidMethodBuilder - it&amp;#39;s mine. And my SetResult method in this project does &lt;em&gt;absolutely nothing&lt;/em&gt;. How convenient!&lt;/p&gt;  &lt;h2&gt;Make it stop, make it stop!&lt;/h2&gt;  &lt;p&gt;Okay thiat was a pretty quick tour of some horrible code. You&amp;#39;ll never have to do anything like this with async in sane code, but it certainly made me painfully familiar with how it all worked. Just to recap on the oddities involved:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;We needed to capture a continuation and then immediately keep going, &lt;em&gt;almost&lt;/em&gt; as if the awaiter had said the awaitable had completed already. This involved shenanigans with the execution model and an extra method (Execute)&lt;/li&gt;    &lt;li&gt;We needed to remember the state of a continuation, which we did with reflection.&lt;/li&gt;    &lt;li&gt;We needed to make awaiter.GetResult() a valid call after awaiter had been reset to the default value for the type&lt;/li&gt;    &lt;li&gt;We needed to ensure that the builder created in the skeleton method could have SetResult called on it multiple times&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;That&amp;#39;s all on continuations and co-routines, I promise.&lt;/p&gt;  &lt;p&gt;Next time (hopefully soon) I&amp;#39;ll look at an example of how composition works so neatly in async, and then show how we can unit test async methods - at least sometimes.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1802363" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/Evil+Code/default.aspx">Evil Code</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/C_2300_+5/default.aspx">C# 5</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/Eduasync/default.aspx">Eduasync</category></item></channel></rss>