<?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 : C#, C# 5, Wacky Ideas</title><link>http://msmvps.com/blogs/jon_skeet/archive/tags/C_2300_/C_2300_+5/Wacky+Ideas/default.aspx</link><description>Tags: C#, C# 5, Wacky Ideas</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP2 (Build: 40407.4157)</generator><item><title>Eduasync part 13: first look at coroutines with async</title><link>http://msmvps.com/blogs/jon_skeet/archive/2011/06/22/eduasync-part-13-first-look-at-coroutines-with-async.aspx</link><pubDate>Wed, 22 Jun 2011 20:37:30 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1795089</guid><dc:creator>skeet</dc:creator><slash:comments>14</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/rsscomments.aspx?PostID=1795089</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/commentapi.aspx?PostID=1795089</wfw:comment><comments>http://msmvps.com/blogs/jon_skeet/archive/2011/06/22/eduasync-part-13-first-look-at-coroutines-with-async.aspx#comments</comments><description>&lt;p&gt;(This part covers project 18 in the &lt;a href="http://code.google.com/p/eduasync/source/browse/"&gt;source code&lt;/a&gt;.)&lt;/p&gt;  &lt;p&gt;As I mentioned in earlier parts, the &amp;quot;awaiting&amp;quot; part of async methods is in no way limited to tasks. So long as we have a suitable GetAwaiter() method which returns a value of a type which in turn has suitable methods on it, the compiler doesn&amp;#39;t really care what&amp;#39;s going on. It&amp;#39;s time to exploit that to implement some form of &lt;a href="http://en.wikipedia.org/wiki/Coroutine"&gt;coroutines&lt;/a&gt; in C#.&lt;/p&gt;  &lt;h3&gt;Introduction to coroutines&lt;/h3&gt;  &lt;p&gt;The fundamental idea of coroutines is to have multiple methods executing cooperatively, each of them maintaining their position within the coroutine when they yield to another. You can &lt;em&gt;almost&lt;/em&gt; think of them as executing in multiple threads, with only one thread actually &lt;em&gt;running&lt;/em&gt; at a time, and signalling between the different threads to control flow. However, we don&amp;#39;t really need multiple threads once we&amp;#39;ve got continuations - we can have a single thread with a complex flow of continuations, and still only a very short &amp;quot;real&amp;quot; stack. (The control flow is stored in normal collections instead of being implicit on the thread&amp;#39;s stack.)&lt;/p&gt;  &lt;p&gt;Coroutines were already feasible in C# through the use of iterator blocks, but the async feature of C# allows a slightly more natural way of expressing them, in my view. (The linked Wikipedia page gives a sketch of how coroutines can be built on top of &lt;em&gt;generators&lt;/em&gt;, which in the general concept that iterator blocks implement in C#.)&lt;/p&gt;  &lt;p&gt;I have implemented various flavours of coroutines in Eduasync. It&amp;#39;s possible that some (all?) of them shouldn&amp;#39;t &lt;em&gt;strictly &lt;/em&gt;be called coroutines, but they&amp;#39;re close enough to the real thing in feeling. This is far from an exhaustive set of approaches. Once you&amp;#39;ve got the basic idea of what I&amp;#39;m doing, you may well want to experiment with your own implementations.&lt;/p&gt;  &lt;p&gt;I&amp;#39;m &lt;em&gt;not&lt;/em&gt; going to claim that the use of coroutines in any of my examples really makes any sense in terms of making real tasks easier. This is &lt;em&gt;purely&lt;/em&gt; for the sake of interest and twisting the async feature for fun.&lt;/p&gt;  &lt;h3&gt;Round-robin independent coroutines&lt;/h3&gt;  &lt;p&gt;Our first implementation of coroutines is relatively simple. A &lt;em&gt;coordinator&lt;/em&gt; effectively &amp;quot;schedules&amp;quot; the coroutines it&amp;#39;s set up with in a round-robin fashion: when one of the coroutines yields control to the coordinator, the coordinator remembers where the coroutine had got to, and then starts the next one. When each coroutine has executed its first piece of code and yielded control, the coordinator will go back to the first coroutine to continue execution, and so on until all coroutines have completed.&lt;/p&gt;  &lt;p&gt;The coroutines don&amp;#39;t know about each other, and no data is being passed between them.&lt;/p&gt;  &lt;p&gt;Hopefully it&amp;#39;s reasonably obvious that the coordinator contains all the smarts here - the coroutines themselves can be relatively dumb. Let&amp;#39;s look at what the client code looks like (along with the results) before we get to the coordinator code.&lt;/p&gt;  &lt;h3&gt;Client code&lt;/h3&gt;  &lt;p&gt;The sample code contains three coroutines, all of which take a Coordinator parameter and have a void return type. These are passed to a new coordinator using a collection initializer and method group conversions; the coordinator is then started. Here&amp;#39;s the entry point code for this:&lt;/p&gt;  &lt;div class="code"&gt;&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;{     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Linq"&gt;var&lt;/span&gt; coordinator = &lt;span class="Keyword"&gt;new&lt;/span&gt; Coordinator {&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; FirstCoroutine,     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; SecondCoroutine,     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ThirdCoroutine     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; };     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; coordinator.Start();     &lt;br /&gt;} &lt;/div&gt;  &lt;p&gt;When each coroutine is initially started, the coordinator passes a reference to &lt;em&gt;itself&lt;/em&gt; as the argument to the coroutine. That&amp;#39;s how we solve the chicken-and-egg problem of the coroutine and coordinator having to know about each other. The way a coroutine yields control is simply by awaiting the coordinator. The result type of this await expression is void - it&amp;#39;s just a way of &amp;quot;pausing&amp;quot; the coroutine.&lt;/p&gt;  &lt;p&gt;We&amp;#39;re not doing anything interesting in the actual coroutines - just tracing the execution flow. Of course we &lt;em&gt;could&lt;/em&gt; do anything we wanted, within reason. We could even await a &lt;em&gt;genuinely&lt;/em&gt; asynchronous task such as fetching a web page asynchronously. In that case the whole coroutine collection would be &amp;quot;paused&amp;quot; until the fetch returned.&lt;/p&gt;  &lt;p&gt;Here&amp;#39;s the code for the first coroutine - the second and third ones are similar, but use different indentation for clarity. The third coroutine is also shorter, just for fun - it only awaits the coordinator once.&lt;/p&gt;  &lt;div class="code"&gt;&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; FirstCoroutine(Coordinator coordinator)     &lt;br /&gt;{     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Console.WriteLine(&lt;span class="String"&gt;&amp;quot;Starting FirstCoroutine&amp;quot;&lt;/span&gt;);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Console.WriteLine(&lt;span class="String"&gt;&amp;quot;Yielding from FirstCoroutine...&amp;quot;&lt;/span&gt;);     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;await&lt;/span&gt; coordinator;     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Console.WriteLine(&lt;span class="String"&gt;&amp;quot;Returned to FirstCoroutine&amp;quot;&lt;/span&gt;);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Console.WriteLine(&lt;span class="String"&gt;&amp;quot;Yielding from FirstCoroutine again...&amp;quot;&lt;/span&gt;);     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;await&lt;/span&gt; coordinator;     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Console.WriteLine(&lt;span class="String"&gt;&amp;quot;Returned to FirstCoroutine again&amp;quot;&lt;/span&gt;);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Console.WriteLine(&lt;span class="String"&gt;&amp;quot;Finished FirstCoroutine&amp;quot;&lt;/span&gt;);     &lt;br /&gt;} &lt;/div&gt;  &lt;p&gt;And here&amp;#39;s the output...&lt;/p&gt;  &lt;div class="code"&gt;Starting FirstCoroutine    &lt;br /&gt;Yielding from FirstCoroutine...     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Starting SecondCoroutine     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Yielding from SecondCoroutine...     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Starting ThirdCoroutine     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Yielding from ThirdCoroutine...     &lt;br /&gt;Returned to FirstCoroutine     &lt;br /&gt;Yielding from FirstCoroutine again...     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Returned to SecondCoroutine     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Yielding from SecondCoroutine again...     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Returned to ThirdCoroutine     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Finished ThirdCoroutine...     &lt;br /&gt;Returned to FirstCoroutine again     &lt;br /&gt;Finished FirstCoroutine     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Returned to SecondCoroutine again     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Finished SecondCoroutine &lt;/div&gt;  &lt;p&gt;Hopefully that&amp;#39;s the output you expected, given the earlier description. Again it may help if you think of the coroutines as running in separate pseudo-threads: the execution within each pseudo-thread is just linear, and the timing is controlled by our explicit &amp;quot;await&amp;quot; expressions. All of this would actually be pretty easy to implement using multiple threads which really &lt;em&gt;did&lt;/em&gt; just block on each await expression - but the fun part is keeping it all in one real thread. Let&amp;#39;s have a look at the coordinator.&lt;/p&gt;  &lt;h3&gt;The Coordinator class&lt;/h3&gt;  &lt;p&gt;Some of the later coroutine examples end up being slightly brainbusting, at least for me. This one is relatively straightforward though, once you&amp;#39;ve got the basic idea. All we need is a &lt;em&gt;queue&lt;/em&gt; of actions to execute. After initialization, we want our queue to contain the coroutine starting points.&lt;/p&gt;  &lt;p&gt;When a coroutine yields control, we just need to add the remainder of it to the end of the queue, and move on to the next item. Obviously the async infrastructure will provide &amp;quot;the remainder of the coroutine&amp;quot; as a continuation via the OnContinue method.&lt;/p&gt;  &lt;p&gt;When a coroutine just returns, we continue with the next item in the queue as before - it&amp;#39;s just that we won&amp;#39;t add a continuation to the end of the queue. Eventually (well, hopefully) we&amp;#39;ll end up with an empty queue, at which point we can stop.&lt;/p&gt;  &lt;h3&gt;Initialization and a choice of data structures&lt;/h3&gt;  &lt;p&gt;We&amp;#39;ll represent our queue using Queue&amp;lt;T&amp;gt; where the T is a delegate type. We have two choices here though, because we have two kinds of delegate - one which takes the Coordinator as a parameter (for the initial coroutine setup) and one which has no parameters (for the continuations). Fortunately we can convert between the two in either direction very simply, bearing in mind that all of this is within the context of a coordinator. For example:&lt;/p&gt;  &lt;div class="code"&gt;&lt;span class="InlineComment"&gt;// If we&amp;#39;re given a coroutine and want a plain Action &lt;/span&gt;    &lt;br /&gt;Action&amp;lt;Coordinator&amp;gt; coroutine = ...;&amp;#160; &lt;br /&gt;Action action = () =&amp;gt; coroutine(&lt;span class="Keyword"&gt;this&lt;/span&gt;);    &lt;br /&gt;    &lt;br /&gt;&lt;span class="InlineComment"&gt;// If we&amp;#39;re given a plain Action and want an Action&amp;lt;Continuation&amp;gt;: &lt;/span&gt;    &lt;br /&gt;Action continuation = ...;&amp;#160; &lt;br /&gt;Action&amp;lt;Coordinator&amp;gt; coroutine = ignored =&amp;gt; continuation(); &lt;/div&gt;  &lt;p&gt;I&amp;#39;ve arbitrarily chosen to use the first option, so there&amp;#39;s a Queue&amp;lt;Action&amp;gt; internally.&lt;/p&gt;  &lt;p&gt;Now we need to get the collection initializer working. The C# compiler requires an appropriate Add method (which is easy) and also checks that the type implements IEnumerable. We don&amp;#39;t really need to be able to iterate over the queue of actions, so I&amp;#39;ve use explicit interface implementation to reduce the likelihood of GetEnumerator() being called inappropriately, and made the method throw an exception for good measure. That gives us the skeleton of the class required for setting up:&lt;/p&gt;  &lt;div class="code"&gt;&lt;span class="Modifier"&gt;public&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; Coordinator : IEnumerable    &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; Queue&amp;lt;Action&amp;gt; actions = &lt;span class="Keyword"&gt;new&lt;/span&gt; Queue&amp;lt;Action&amp;gt;();    &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="InlineComment"&gt;// Used by collection initializer to specify the coroutines to run&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;void&lt;/span&gt; Add(Action&amp;lt;Coordinator&amp;gt; coroutine)    &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; actions.Enqueue(() =&amp;gt; coroutine(&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;// Required for collection initializers, but we don&amp;#39;t really want&lt;/span&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="InlineComment"&gt;// to expose anything.&lt;/span&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; IEnumerator IEnumerable.GetEnumerator()    &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;throw&lt;/span&gt;&amp;#160;&lt;span class="Keyword"&gt;new&lt;/span&gt; NotSupportedException(&lt;span class="String"&gt;&amp;quot;IEnumerable only supported to enable collection initializers&amp;quot;&lt;/span&gt;);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;} &lt;/div&gt;  &lt;p&gt;(Note that I haven&amp;#39;t used XML documentation anywhere here - it&amp;#39;s great for real code, but adds clutter in blog posts.)&lt;/p&gt;  &lt;p&gt;For production code I&amp;#39;d probably prevent Add from being called after the coordinator had been started, but there&amp;#39;s no need to do it in our well-behaved sample code. We&amp;#39;re only going to add extra actions to the queue via continuations, which will be added due to await expressions.&lt;/p&gt;  &lt;h3&gt;The main execution loop and async infrastructure&lt;/h3&gt;  &lt;p&gt;So far we&amp;#39;ve got code to register coroutines in the queue - so now we need to execute them. Bearing in mind that the actions themselves will be responsible for adding continuations, the main loop of the coordinator is embarrassingly simple:&lt;/p&gt;  &lt;div class="code"&gt;&lt;span class="InlineComment"&gt;// Execute actions in the queue until it&amp;#39;s empty. Actions add *more*&lt;/span&gt;    &lt;br /&gt;&lt;span class="InlineComment"&gt;// actions (continuations) to the queue by awaiting this coordinator.&lt;/span&gt;    &lt;br /&gt;&lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;#160;&lt;span class="ValueType"&gt;void&lt;/span&gt; Start()    &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Statement"&gt;while&lt;/span&gt; (actions.Count &amp;gt; 0)    &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; actions.Dequeue().Invoke();    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;} &lt;/div&gt;  &lt;p&gt;Of course, the interesting bit is the code which supports the async methods and await expressions. We know we need to provide a GetAwaiter() method, but what should that return? Well, we&amp;#39;re just going to use the awaiter to add a continuation to the coordinator&amp;#39;s queue. It&amp;#39;s got no other state than that - so we might as well return the coordinator itself, and put the other infrastructure methods directly in the coordinator.&lt;/p&gt;  &lt;p&gt;Again, this is &lt;em&gt;slightly&lt;/em&gt; ugly, as the extra methods don&amp;#39;t really make sense on the coordinator - we wouldn&amp;#39;t want to call them directly from client code, for example. However, they&amp;#39;re fairly irrelevant - we could always create a nested type which just had a reference to its &amp;quot;parent&amp;quot; coordinator if we wanted to. For simplicity, I haven&amp;#39;t bothered with this - I&amp;#39;ve just implemented GetAwaiter() trivially:&lt;/p&gt;  &lt;div class="code"&gt;&lt;span class="InlineComment"&gt;// Used by await expressions to get an awaiter&lt;/span&gt;    &lt;br /&gt;&lt;span class="Modifier"&gt;public&lt;/span&gt; Coordinator GetAwaiter()    &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;this&lt;/span&gt;;    &lt;br /&gt;} &lt;/div&gt;  &lt;p&gt;So, that leaves just three members still to implement: IsCompleted, OnCompleted and GetResult. We always want the IsCompleted property to return false, as otherwise the coroutine will just continue executing &lt;em&gt;immediately&lt;/em&gt; without returning to cede control; the await expression would be pointless. OnCompleted &lt;em&gt;just&lt;/em&gt; needs to add the continuation to the end of the queue - we don&amp;#39;t need to attach it to a task, or anything like that. Finally, GetResult is a no-op - we have no results, no exceptions, and basically nothing to do. You might want to add a bit of logging here, if you were so inclined, but there&amp;#39;s no real need.&lt;/p&gt;  &lt;p&gt;So, here are the final three members of Coordinator:&lt;/p&gt;  &lt;div class="code"&gt;&lt;span class="InlineComment"&gt;// Force await to yield control&lt;/span&gt;    &lt;br /&gt;&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;&lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;#160;&lt;span class="ValueType"&gt;void&lt;/span&gt; OnCompleted(Action continuation)    &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="InlineComment"&gt;// Put the continuation at the end of the queue, ready to&lt;/span&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="InlineComment"&gt;// execute when the other coroutines have had a go.&lt;/span&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; actions.Enqueue(continuation);    &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;void&lt;/span&gt; GetResult()    &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="InlineComment"&gt;// Our await expressions are void, and we never need to throw&lt;/span&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="InlineComment"&gt;// an exception, so this is a no-op.&lt;/span&gt;    &lt;br /&gt;} &lt;/div&gt;  &lt;p&gt;And that&amp;#39;s it! Fewer than 50 lines of code required, and nothing complicated at all. The interesting behaviour is all due to the way the C# compiler &lt;em&gt;uses&lt;/em&gt; the coordinator when awaiting it.&lt;/p&gt;  &lt;p&gt;We need AsyncVoidMethodBuilder as before, as we have some async void methods - but that doesn&amp;#39;t need to do anything significant. That&amp;#39;s basically all the code required to implement these basic round-robin coroutines.&lt;/p&gt;  &lt;h3&gt;Conclusion&lt;/h3&gt;  &lt;p&gt;Our first foray into the weird and wonderful world of coroutines was relatively tame. The basic idea of a coordinator keeping track of the state of all the different coroutines in one sense or another will keep coming back to us, but with different ways of controlling the execution flow.&lt;/p&gt;  &lt;p&gt;Next time we&amp;#39;ll see some coroutines which can pass data to each other.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1795089" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/Wacky+Ideas/default.aspx">Wacky Ideas</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/async/default.aspx">async</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/Eduasync/default.aspx">Eduasync</category></item></channel></rss>