<?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>Peter Ritchie's MVP Blog : Async Functions, .NET Development</title><link>http://msmvps.com/blogs/peterritchie/archive/tags/Async+Functions/.NET+Development/default.aspx</link><description>Tags: Async Functions, .NET Development</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP2 (Build: 40407.4157)</generator><item><title>C#, Async, Limits, oh my!</title><link>http://msmvps.com/blogs/peterritchie/archive/2012/01/19/c-async-limits-oh-my.aspx</link><pubDate>Thu, 19 Jan 2012 18:54:35 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1805090</guid><dc:creator>PeterRitchie</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/peterritchie/rsscomments.aspx?PostID=1805090</wfw:commentRss><comments>http://msmvps.com/blogs/peterritchie/archive/2012/01/19/c-async-limits-oh-my.aspx#comments</comments><description>&lt;p&gt;One of the great sessions at &lt;a href="http://codemash.org"&gt;Codemash&lt;/a&gt; was a dual-speaker session with Bill Wagner and Jon Skeet—&lt;em&gt;&lt;a href="http://codemash.org/Sessions/Technology/.NET#Async+From+the+Inside"&gt;Async from the Inside&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;  &lt;p&gt;In that session Bill and Jon describe (in great detail) the state machine that the C# compiler generates when it compiles async code involving the await keyword.&amp;#160; When the Async CTP was released this state machine was one of the first things I noticed when I was reflecting through some generated code.&amp;#160; I too noticed the type of the state variable (int) and wondered, at the time, if that would be an issue.&amp;#160; All the information Bill, Jon and I portray is what we’ve learned from reflection, none of this is “insider information”.&lt;/p&gt;  &lt;p&gt;Some background: a state machine is generated for each method that uses the await keyword.&amp;#160; It manages weaving back-together the asynchronous calls that you so lovingly linearly describe in an async method.&amp;#160; The state machine not only weaves together the various “callbacks” that it generates, but it also (now) manages the state changes of the data being modified between and by asynchronous calls.&amp;#160; Wonderfully complex stuff.&lt;/p&gt;  &lt;p&gt;The state variable is basically an enum of the various states between async calls that the generated code can be in.&amp;#160; I won’t get into too much detail about that (you should have gone Codemash like all the other cool people :) but needless to say having a “limit” on the number of states a method can be in sounds a bit scary.&lt;/p&gt;  &lt;p&gt;Of course Jon, at one point, brought the same thing up in the session about the “int” state variable.&amp;#160; This reminded me that I wanted to look into it further—not because I wanted to break the compiler (directly) but to know what the limits are, if any.&lt;/p&gt;  &lt;p&gt;A couple of days later while I had some time waiting around at airports on my way home.&amp;#160; I thought I’d test my theory.&amp;#160; If you follow me on &lt;a href="http://twitter.com/peterritchie"&gt;Twitter&lt;/a&gt; you probably saw some of my discoveries in real time.&amp;#160; For those of you who didn’t, here’s an aggregation of what I found.&lt;/p&gt;  &lt;p&gt;First of all, the state machine represents the async states a single method can be in.&amp;#160; This is represented by a signed int.&amp;#160; the only negative value that seems [1] to mean anything is –1, leaving 2,147,483,647 states (or, roughly, await invocations) that can occur in an async method.&lt;/p&gt;  &lt;p&gt;First glance, this seems disconcerting.&amp;#160; I quickly wrote some code to generate a method with 2,147,483,648 await invocations in it (that’s Int32.MaxValue + 1 for those without OCD).&amp;#160; Needless to say, that took a few minutes to generate on my laptop, and I have an SSD (which I’ve clocked at increasing my IO by about 7 times on average).&amp;#160; That generated a 45 gigabyte file (one class, one method).&lt;/p&gt;  &lt;p&gt;Problems with the type int for the state variable started to seem ridiculous.&amp;#160; But, I didn’t stop there.&lt;/p&gt;  &lt;p&gt;Now I’m doing everything outside of Visual Studio (VS) from this point on.&amp;#160; I’m running the app to generate the code from within VS; but everything else is from the command-line.&amp;#160; So, I run CSC on the 45 gig file honestly expecting and internal compiler error.&amp;#160; But, what happens is that I get a CS1504 error &lt;em&gt;‘file.cs’ could not be opened (‘Arithmetic result exceeded 32-bits. ‘).&lt;/em&gt;&amp;#160; Now, the state variable is 32-bits so, it sounds like that could be the culprit.&amp;#160; But, if you look at the error message, it can’t even open the file.&amp;#160; I tried opening the file in VS and it told me the file couldn’t be found…&lt;/p&gt;  &lt;p&gt;Okay, at this point it’s seeming even more unlikely that a type of int for the state variable is even remotely going to be an issue.&amp;#160; But, now I’m curious about what 32-bit value has been exceeded.&amp;#160; My theory is now the number of lines in the file…&amp;#160; The compiler has to keep track of each line in the file in case it has to dump an error about it, maybe that’s the 32-bit value? I modify my code generation to limit the the number of await invocations so the number of lines in the file is 2,147,483,647 (kind of a binary search, if this works then I know it still could be the number of lines in the file). Same error.&lt;/p&gt;  &lt;p&gt;The error isn’t from the # of lines.&amp;#160; Now my theory is that the overflow is from trying to allocate enough memory load the file (keep in mind, I’ve got 8 GB of RAM and I’m trying to load a 45GB file; but, I have yet to get an out of memory error).&amp;#160; So, I modify my code to generate a file that is approaching 2,147,483,647 bytes in size.&amp;#160; Things are much faster now…&amp;#160; I try again. Now I get the same CS1504 error but the message is &lt;em&gt;‘file.cs’ could not be opened (‘Not enough storage available to complete this operation’)&lt;/em&gt; (I’ve got 100 GB free space on the drive…).&amp;#160; Interesting.&amp;#160; I’ve lessened the data requirement and only now effectively getting “out of memory” errors.&lt;/p&gt;  &lt;p&gt;Now I’m just looking for a file that the compiler will load—I’ve given up on some super-large number of await statements…&amp;#160; Longer story, short, I kept halving the size of the file until I reached about 270 megabytes in size then the compiler finally succeeded (meaning ~540 Megabytes failed).&lt;/p&gt;  &lt;p&gt;At this point, I’ve successfully proven that a type of int for the state variable is not an issue.&amp;#160; &lt;em&gt;If&lt;/em&gt; the compiler &lt;em&gt;could&lt;/em&gt; load the 540 megabyte file &lt;em&gt;and&lt;/em&gt; I somehow &lt;em&gt;could&lt;/em&gt; use 8 bytes per await invocation (“await x;” for example) then I could never reach more than about 70,778,880 await calls in a single method.&amp;#160; Of course, I’m way off here; that number is even much lower; but 70,778,880 is about 3% of 2,147,483,647.&amp;#160; Clearly int is the smallest type that could store anything close to 70,778,880 or less…&lt;/p&gt;  &lt;p&gt;Of course, I’m completely ignoring the fact that a 540 MB cs file is completely unmanageable in VS or a project in general; but, why get caught up in silly realities like that.&lt;/p&gt;  &lt;p&gt;This state machine is almost identical to those generated by enumerator methods (yield return).&amp;#160; If we assumed that the async state machine generation code is “inherited” (by pragmatic reuse) from the enumerator method state machine generator, we can assume it has very similar limits (but even smaller)—meaning you’d never get close to overflowing its int state variable.&lt;/p&gt;  &lt;p&gt;HTMYL.&lt;/p&gt;  &lt;p&gt;[1] Again, this all observed; I’m surmising the compiler never uses any other negative value.&lt;/p&gt;&lt;div class="wlWriterHeaderFooter" style="margin:0px;padding:4px 0px 4px 0px;"&gt;&lt;iframe src="http://www.facebook.com/widgets/like.php?href=http://msmvps.com/blogs/peterritchie/archive/2012/01/19/c-async-limits-oh-my.aspx" scrolling="no" frameborder="0" style="border:none;width:325px;height:80px;"&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;div class="wlWriterHeaderFooter" style="margin:0px;padding:0px 0px 0px 0px;"&gt; &lt;script type="text/javascript"&gt;
  (function() {
    var po = document.createElement(&amp;#39;script&amp;#39;); po.type = &amp;#39;text/javascript&amp;#39;; po.async = true;
    po.src = &amp;#39;https://apis.google.com/js/plusone.js&amp;#39;;
    var s = document.getElementsByTagName(&amp;#39;script&amp;#39;)[0]; s.parentNode.insertBefore(po, s);
  })();
&lt;/script&gt;&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1805090" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/.NET+Development/default.aspx">.NET Development</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/Async+Functions/default.aspx">Async Functions</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/Visual+Studio/default.aspx">Visual Studio</category></item><item><title>Testing Strategies Involving Async Functions</title><link>http://msmvps.com/blogs/peterritchie/archive/2010/11/04/testing-strategies-involving-async-functions.aspx</link><pubDate>Thu, 04 Nov 2010 16:26:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1781600</guid><dc:creator>PeterRitchie</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/peterritchie/rsscomments.aspx?PostID=1781600</wfw:commentRss><comments>http://msmvps.com/blogs/peterritchie/archive/2010/11/04/testing-strategies-involving-async-functions.aspx#comments</comments><description>&lt;p&gt;Some things to keep in mind when writing units tests for code that use 
async methods: You&amp;#39;re not trying to test the framework&amp;#39;s &amp;quot;awaitability&amp;quot; 
and you&amp;#39;re not trying to test framework methods that are &amp;quot;awaitable&amp;quot;.&amp;nbsp; 
You want to test your code in certain isolation contexts.&amp;nbsp; One context, 
of course, is independent of asynchronicity--do individual units of code
 that don&amp;#39;t depend on asynchronous invocation &amp;quot;work&amp;quot;...&amp;nbsp; e.g. 
&amp;quot;Task&amp;lt;string&amp;gt; MyMethodAsync()&amp;quot;, you want to have a unit test that 
make sure this method does what it&amp;#39;s supposed to do (one being it 
returns a &amp;quot;valid&amp;quot; Task&amp;lt;string&amp;gt; object, the other being that 
individual side-effects occur, if any).&amp;nbsp; Another context is dependent on
 asynchronicity--do individual units of code that do depend on 
asynchronous invocation (or depend on something being invoked 
asynchronously) &amp;quot;work&amp;quot;.&amp;nbsp; &lt;br /&gt;
&lt;br /&gt;
It&amp;#39;s the second context that seems to be the hardest to grasp for most 
people to grasp and action.&amp;nbsp;&amp;nbsp;
Let&amp;#39;s take this example code:&lt;/p&gt;
&lt;pre style="font-family:consolas;"&gt;	&lt;span style="color:blue;"&gt;private&lt;/span&gt;&amp;nbsp;&lt;span style="color:blue;"&gt;async&lt;/span&gt;&amp;nbsp;&lt;span style="color:blue;"&gt;void&lt;/span&gt;&amp;nbsp;startButton_Click(&lt;span style="color:blue;"&gt;object&lt;/span&gt;&amp;nbsp;sender,&amp;nbsp;&lt;span style="color:#2b91af;"&gt;EventArgs&lt;/span&gt;&amp;nbsp;e)&lt;br /&gt;	{&lt;br /&gt;		&lt;span style="color:blue;"&gt;try&lt;/span&gt;&lt;br /&gt;		{&lt;br /&gt;			startButton.Enabled&amp;nbsp;=&amp;nbsp;&lt;span style="color:blue;"&gt;false&lt;/span&gt;;&lt;br /&gt;			&lt;span style="color:blue;"&gt;var&lt;/span&gt;&amp;nbsp;webRequest&amp;nbsp;=&amp;nbsp;&lt;span style="color:#2b91af;"&gt;WebRequest&lt;/span&gt;.Create(&lt;span style="color:#a31515;"&gt;&amp;quot;http://google.ca&amp;quot;&lt;/span&gt;);&lt;br /&gt;			&lt;span style="color:blue;"&gt;using&lt;/span&gt;&amp;nbsp;(&lt;span style="color:blue;"&gt;var&lt;/span&gt;&amp;nbsp;response&amp;nbsp;=&amp;nbsp;&lt;span style="color:blue;"&gt;await&lt;/span&gt;&amp;nbsp;webRequest.GetResponseAsync())&lt;br /&gt;			&lt;span style="color:blue;"&gt;using&lt;/span&gt;&amp;nbsp;(&lt;span style="color:blue;"&gt;var&lt;/span&gt;&amp;nbsp;stream&amp;nbsp;=&amp;nbsp;response.GetResponseStream())&lt;br /&gt;			{&lt;br /&gt;				&lt;span style="color:blue;"&gt;if&lt;/span&gt;&amp;nbsp;(stream&amp;nbsp;==&amp;nbsp;&lt;span style="color:blue;"&gt;null&lt;/span&gt;)&amp;nbsp;&lt;span style="color:blue;"&gt;return&lt;/span&gt;;&lt;br /&gt;				&lt;span style="color:blue;"&gt;using&lt;/span&gt;&amp;nbsp;(&lt;span style="color:blue;"&gt;var&lt;/span&gt;&amp;nbsp;reader&amp;nbsp;=&amp;nbsp;&lt;span style="color:blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color:#2b91af;"&gt;StreamReader&lt;/span&gt;(stream))&lt;br /&gt;				{&lt;br /&gt;					textBox.Text&amp;nbsp;=&amp;nbsp;&lt;span style="color:blue;"&gt;await&lt;/span&gt;&amp;nbsp;reader.ReadToEndAsync();&lt;br /&gt;				}&lt;br /&gt;			}&lt;br /&gt;		}&lt;br /&gt;		&lt;span style="color:blue;"&gt;finally&lt;/span&gt;&lt;br /&gt;		{&lt;br /&gt;			startButton.Enabled&amp;nbsp;=&amp;nbsp;&lt;span style="color:blue;"&gt;true&lt;/span&gt;;&lt;br /&gt;		}&lt;br /&gt;	}&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;A couple invariants that we want to test might be that the button is disabled during the asynchronous operations and enabled after the asynchronous operations.&amp;nbsp; It&amp;#39;s not immediately obvious what to in order to validate these invariants.&lt;/p&gt;
&lt;p&gt;When the compiler encounters the await operator, it actually goes searching for method that can act upon the type of the object being returned by the method used with the await operator.&amp;nbsp; In our first use of await (on GetResponseAsync()) the return type is Task&amp;lt;T&amp;gt; (Task&amp;lt;WebResponse&amp;gt; specifically, but for our example I&amp;#39;ll use Task&amp;lt;T&amp;gt;).&amp;nbsp; There&amp;#39;s various criteria the computer uses to search for this method, one method is to search for extension methods that match the name and return an &amp;quot;awaiter&amp;quot; type that has the following methods: BeginAwait and EndAwait (more details can be found in the Aync CTP documentation).&amp;nbsp; The compiler doesn&amp;#39;t allow us to inject an awaiter type in the normal run-time dependency injection semantics; but it does allow us to implement an awaiter that does support dependency injection at run-time.&amp;nbsp; To do this I would create an ITaskAwaiter interface like this:&lt;/p&gt;
&lt;pre style="font-family:consolas;"&gt;	&lt;span style="color:blue;"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color:blue;"&gt;interface&lt;/span&gt;&amp;nbsp;&lt;span style="color:#2b91af;"&gt;ITaskAwaiter&lt;/span&gt;&amp;lt;&lt;span style="color:blue;"&gt;out&lt;/span&gt;&amp;nbsp;T&amp;gt;&lt;br /&gt;	{&lt;br /&gt;		&lt;span style="color:blue;"&gt;bool&lt;/span&gt;&amp;nbsp;BeginAwait(&lt;span style="color:#2b91af;"&gt;Action&lt;/span&gt;&amp;nbsp;continuation);&lt;br /&gt;		T&amp;nbsp;EndAwait();&lt;br /&gt;	}&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;I then need to create a GetAwaiter(this Task&amp;lt;T&amp;gt;) extension method to return an implementation of this type.&amp;nbsp; The built-in System.Runtime.CompilerServices.TaskAwaiter&amp;lt;T&amp;gt; is public; but, unfortunately it&amp;#39;s constructor (and the ability to pass in a Task&amp;lt;T&amp;gt;) object is internal.&amp;nbsp; So, we can&amp;#39;t simply wrap the built-in awaiter and delegate to it as a default.&amp;nbsp; We actually have to write an awaiter that mimics what the built-in one does.&amp;nbsp; For example:&lt;/p&gt;
&lt;pre style="font-family:consolas;"&gt;	&lt;span style="color:blue;"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color:blue;"&gt;class&lt;/span&gt;&amp;nbsp;&lt;span style="color:#2b91af;"&gt;TaskAwaiter&lt;/span&gt;&amp;lt;T&amp;gt;&amp;nbsp;:&amp;nbsp;&lt;span style="color:#2b91af;"&gt;ITaskAwaiter&lt;/span&gt;&amp;lt;T&amp;gt;&lt;br /&gt;	{&lt;br /&gt;		&lt;span style="color:blue;"&gt;private&lt;/span&gt;&amp;nbsp;&lt;span style="color:blue;"&gt;readonly&lt;/span&gt;&amp;nbsp;&lt;span style="color:#2b91af;"&gt;Task&lt;/span&gt;&amp;lt;T&amp;gt;&amp;nbsp;task;&lt;br /&gt; &lt;br /&gt;		&lt;span style="color:blue;"&gt;public&lt;/span&gt;&amp;nbsp;TaskAwaiter(&lt;span style="color:#2b91af;"&gt;Task&lt;/span&gt;&amp;lt;T&amp;gt;&amp;nbsp;task)&lt;br /&gt;		{&lt;br /&gt;			&lt;span style="color:blue;"&gt;this&lt;/span&gt;.task&amp;nbsp;=&amp;nbsp;task;&lt;br /&gt;		}&lt;br /&gt; &lt;br /&gt;		&lt;span style="color:blue;"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color:blue;"&gt;bool&lt;/span&gt;&amp;nbsp;BeginAwait(&lt;span style="color:#2b91af;"&gt;Action&lt;/span&gt;&amp;nbsp;continuation)&lt;br /&gt;		{&lt;br /&gt;			&lt;span style="color:blue;"&gt;if&lt;/span&gt;&amp;nbsp;(task.IsCompleted)&amp;nbsp;&lt;span style="color:blue;"&gt;return&lt;/span&gt;&amp;nbsp;&lt;span style="color:blue;"&gt;false&lt;/span&gt;;&lt;br /&gt;			&lt;span style="color:blue;"&gt;var&lt;/span&gt;&amp;nbsp;synchronizationContext&amp;nbsp;=&amp;nbsp;&lt;span style="color:#2b91af;"&gt;SynchronizationContext&lt;/span&gt;.Current;&lt;br /&gt;			&lt;span style="color:#2b91af;"&gt;Action&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;Task&lt;/span&gt;&amp;gt;&amp;nbsp;action&amp;nbsp;=&amp;nbsp;theTask&amp;nbsp;=&amp;gt;&amp;nbsp;&lt;br /&gt;			&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;	{&lt;br /&gt;			&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;		&lt;span style="color:blue;"&gt;if&lt;/span&gt;&amp;nbsp;(synchronizationContext&amp;nbsp;!=&amp;nbsp;&lt;span style="color:blue;"&gt;null&lt;/span&gt;)&lt;br /&gt;			&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;		{&lt;br /&gt;			&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;			synchronizationContext.Post(state&amp;nbsp;=&amp;gt;&amp;nbsp;continuation(),&amp;nbsp;&lt;span style="color:blue;"&gt;null&lt;/span&gt;);&lt;br /&gt;			&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;		}&lt;br /&gt;			&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;		&lt;span style="color:blue;"&gt;else&lt;/span&gt;&lt;br /&gt;			&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;		{&lt;br /&gt;			&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;			continuation();&lt;br /&gt;			&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;		}&lt;br /&gt;			&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;	};&lt;br /&gt; &lt;br /&gt;			task.ContinueWith(action,&amp;nbsp;&lt;span style="color:#2b91af;"&gt;CancellationToken&lt;/span&gt;.None,&amp;nbsp;&lt;span style="color:#2b91af;"&gt;TaskContinuationOptions&lt;/span&gt;.ExecuteSynchronously,&amp;nbsp;&lt;span style="color:#2b91af;"&gt;TaskScheduler&lt;/span&gt;.Current);&lt;br /&gt;			&lt;span style="color:blue;"&gt;return&lt;/span&gt;&amp;nbsp;&lt;span style="color:blue;"&gt;true&lt;/span&gt;;&lt;br /&gt;		}&lt;br /&gt; &lt;br /&gt;		&lt;span style="color:blue;"&gt;public&lt;/span&gt;&amp;nbsp;T&amp;nbsp;EndAwait()&lt;br /&gt;		{&lt;br /&gt;			&lt;span style="color:blue;"&gt;return&lt;/span&gt;&amp;nbsp;task.Result;&lt;br /&gt;		}&lt;br /&gt;	}&lt;/pre&gt;
&lt;p&gt;This class is given the Task&amp;lt;T&amp;gt; in question, it implements a BeginWait method that sets up an Action delegate to invoke the continuation given to it in a specific synchronization context, then tells the task to use that new action as it&amp;#39;s continuation via a call to ContinueWith.&amp;nbsp; When the task is completed EndAwait will be called and we simply return the result of the task.&lt;/p&gt;
&lt;p&gt;Now, in order to add the ability to inject a customer awaiter, we need to provide the GetAwaiter extension method.&amp;nbsp; For example:&lt;/p&gt;
&lt;pre style="font-family:consolas;"&gt;	&lt;span style="color:blue;"&gt;namespace&lt;/span&gt;&amp;nbsp;PRI.Extensions&lt;br /&gt;	{&lt;br /&gt;		&lt;span style="color:blue;"&gt;static&lt;/span&gt;&amp;nbsp;&lt;span style="color:blue;"&gt;class&lt;/span&gt;&amp;nbsp;&lt;span style="color:#2b91af;"&gt;TaskExtensions&lt;/span&gt;&lt;br /&gt;		{&lt;br /&gt;			&lt;span style="color:blue;"&gt;static&lt;/span&gt;&amp;nbsp;&lt;span style="color:blue;"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color:#2b91af;"&gt;ITaskAwaiter&lt;/span&gt;&amp;lt;TResult&amp;gt;&amp;nbsp;GetAwaiter&amp;lt;TResult&amp;gt;(&lt;span style="color:blue;"&gt;this&lt;/span&gt;&amp;nbsp;&lt;span style="color:#2b91af;"&gt;Task&lt;/span&gt;&amp;lt;TResult&amp;gt;&amp;nbsp;task)&lt;br /&gt;			{&lt;br /&gt;				&lt;span style="color:blue;"&gt;return&lt;/span&gt;&amp;nbsp;&lt;span style="color:#2b91af;"&gt;TaskAwaiterFactory&lt;/span&gt;&amp;lt;TResult&amp;gt;.CreateTaskAwaiter&amp;nbsp;!=&amp;nbsp;&lt;span style="color:blue;"&gt;null&lt;/span&gt;&lt;br /&gt;					?&amp;nbsp;&lt;span style="color:#2b91af;"&gt;TaskAwaiterFactory&lt;/span&gt;&amp;lt;TResult&amp;gt;.CreateTaskAwaiter(task)&amp;nbsp;:&amp;nbsp;&lt;span style="color:blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color:#2b91af;"&gt;TaskAwaiter&lt;/span&gt;&amp;lt;TResult&amp;gt;(task);&lt;br /&gt;			}&lt;br /&gt;		}&lt;br /&gt;	}&lt;/pre&gt;
&lt;p&gt;This extension method invokes a factory method delegate to create the ITaskAwaiter&amp;lt;T&amp;gt; object (or simply creates our new default awaiter).&amp;nbsp; This factory method looks like this:&lt;/p&gt;
&lt;pre style="font-family:consolas;"&gt;	&lt;span style="color:blue;"&gt;internal&lt;/span&gt;&amp;nbsp;&lt;span style="color:blue;"&gt;static&lt;/span&gt;&amp;nbsp;&lt;span style="color:blue;"&gt;class&lt;/span&gt;&amp;nbsp;&lt;span style="color:#2b91af;"&gt;TaskAwaiterFactory&lt;/span&gt;&amp;lt;TResult&amp;gt;&lt;br /&gt;	{&lt;br /&gt;		&lt;span style="color:blue;"&gt;private&lt;/span&gt;&amp;nbsp;&lt;span style="color:blue;"&gt;static&lt;/span&gt;&amp;nbsp;&lt;span style="color:#2b91af;"&gt;Func&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;Task&lt;/span&gt;&amp;lt;TResult&amp;gt;,&amp;nbsp;&lt;span style="color:#2b91af;"&gt;ITaskAwaiter&lt;/span&gt;&amp;lt;TResult&amp;gt;&amp;gt;&amp;nbsp;createTaskAwaiter&amp;nbsp;=&amp;nbsp;task&amp;nbsp;=&amp;gt;&lt;br /&gt;		&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;	{&lt;br /&gt;		&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;		Current&amp;nbsp;=&amp;nbsp;&lt;span style="color:blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color:#2b91af;"&gt;TaskAwaiter&lt;/span&gt;&amp;lt;TResult&amp;gt;(task);&lt;br /&gt;		&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;		&lt;span style="color:blue;"&gt;return&lt;/span&gt;&amp;nbsp;Current;&lt;br /&gt;		&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;	};&lt;br /&gt;		&lt;span style="color:blue;"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color:blue;"&gt;static&lt;/span&gt;&amp;nbsp;&lt;span style="color:#2b91af;"&gt;Func&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;Task&lt;/span&gt;&amp;lt;TResult&amp;gt;,&amp;nbsp;&lt;span style="color:#2b91af;"&gt;ITaskAwaiter&lt;/span&gt;&amp;lt;TResult&amp;gt;&amp;gt;&amp;nbsp;CreateTaskAwaiter&lt;br /&gt;		{&lt;br /&gt;			&lt;span style="color:blue;"&gt;get&lt;/span&gt;&amp;nbsp;{&amp;nbsp;&lt;span style="color:blue;"&gt;return&lt;/span&gt;&amp;nbsp;createTaskAwaiter;&amp;nbsp;}&lt;br /&gt;			&lt;span style="color:blue;"&gt;set&lt;/span&gt;&lt;br /&gt;			{&lt;br /&gt;				createTaskAwaiter&amp;nbsp;=&amp;nbsp;task&amp;nbsp;=&amp;gt;&lt;br /&gt;				&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;	{&lt;br /&gt;				&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;		Current&amp;nbsp;=&amp;nbsp;&lt;span style="color:blue;"&gt;value&lt;/span&gt;(task);&lt;br /&gt;				&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;		&lt;span style="color:blue;"&gt;return&lt;/span&gt;&amp;nbsp;Current;&lt;br /&gt;				&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;	};&lt;br /&gt;			}&lt;br /&gt;		}&lt;br /&gt;		&lt;span style="color:blue;"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color:blue;"&gt;static&lt;/span&gt;&amp;nbsp;&lt;span style="color:#2b91af;"&gt;ITaskAwaiter&lt;/span&gt;&amp;lt;TResult&amp;gt;&amp;nbsp;Current&amp;nbsp;{&amp;nbsp;&lt;span style="color:blue;"&gt;get&lt;/span&gt;;&amp;nbsp;&lt;span style="color:blue;"&gt;private&lt;/span&gt;&amp;nbsp;&lt;span style="color:blue;"&gt;set&lt;/span&gt;;&amp;nbsp;}&lt;br /&gt;	}&lt;/pre&gt;
&lt;p&gt;We can override this factory method and give a delegate to code that creates another type of ITaskAwaiter&amp;lt;T&amp;gt; implementation.&amp;nbsp; We also decorate the call to that provided delegate with something that keeps track of the Current awaiter (more on that later).&amp;nbsp; Now, we simply need to add a using statement within our namespace for the compiler to user our GetAwaiter when it compiles an await operator and use our factory.&amp;nbsp; For example:&lt;/p&gt;
&lt;pre style="font-family:consolas;"&gt;	&lt;span style="color:blue;"&gt;namespace&lt;/span&gt;&amp;nbsp;PRI.MainApplication&lt;br /&gt;	{&lt;br /&gt;		&lt;span style="color:blue;"&gt;using&lt;/span&gt;&amp;nbsp;PRI.Extensions;&lt;br /&gt; &lt;br /&gt;		&lt;span style="color:green;"&gt;//...&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;We&amp;#39;re now all set to inject a new awaiter and be able to isolate our code from the framework and validate some invariants.&amp;nbsp; In our case, we&amp;#39;d like to check to make sure that the button is disabled during invocation of asynchronous operations and enabled when done.&amp;nbsp; So, we can create a spy awaiter that basically does nothing and sends back a fake or dummy object.&amp;nbsp; In our example we actually have two different types of Task&amp;lt;T&amp;gt; objects being awaited; so, we need to create a couple of awaiter spys.&amp;nbsp; One is generic and one is specific.&amp;nbsp; For example:&lt;/p&gt;
&lt;pre style="font-family:consolas;"&gt;	&lt;span style="color:blue;"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color:blue;"&gt;class&lt;/span&gt;&amp;nbsp;&lt;span style="color:#2b91af;"&gt;WebResponseTaskAwaiterSpy&lt;/span&gt;&amp;nbsp;:&amp;nbsp;&lt;span style="color:#2b91af;"&gt;ITaskAwaiter&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;WebResponse&lt;/span&gt;&amp;gt;&lt;br /&gt;	{&lt;br /&gt;		&lt;span style="color:blue;"&gt;private&lt;/span&gt;&amp;nbsp;&lt;span style="color:blue;"&gt;class&lt;/span&gt;&amp;nbsp;&lt;span style="color:#2b91af;"&gt;FakeWebResponse&lt;/span&gt;&amp;nbsp;:&amp;nbsp;&lt;span style="color:#2b91af;"&gt;WebResponse&lt;/span&gt;&lt;br /&gt;		{&lt;br /&gt;			&lt;span style="color:blue;"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color:blue;"&gt;override&lt;/span&gt;&amp;nbsp;&lt;span style="color:#2b91af;"&gt;Stream&lt;/span&gt;&amp;nbsp;GetResponseStream()&lt;br /&gt;			{&lt;br /&gt;				&lt;span style="color:blue;"&gt;return&lt;/span&gt;&amp;nbsp;&lt;span style="color:blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color:#2b91af;"&gt;MemoryStream&lt;/span&gt;(System.Text.&lt;span style="color:#2b91af;"&gt;Encoding&lt;/span&gt;.ASCII.GetBytes(&lt;span style="color:#a31515;"&gt;&amp;quot;got&amp;nbsp;some&amp;nbsp;text&amp;quot;&lt;/span&gt;));&lt;br /&gt;			}&lt;br /&gt;		}&lt;br /&gt;		&lt;span style="color:blue;"&gt;private&lt;/span&gt;&amp;nbsp;&lt;span style="color:blue;"&gt;readonly&lt;/span&gt;&amp;nbsp;&lt;span style="color:#2b91af;"&gt;MainForm&lt;/span&gt;&amp;nbsp;form;&lt;br /&gt;		&lt;span style="color:blue;"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color:blue;"&gt;bool&lt;/span&gt;&amp;nbsp;ButtonEnabledState&amp;nbsp;{&amp;nbsp;&lt;span style="color:blue;"&gt;get&lt;/span&gt;;&amp;nbsp;&lt;span style="color:blue;"&gt;private&lt;/span&gt;&amp;nbsp;&lt;span style="color:blue;"&gt;set&lt;/span&gt;;&amp;nbsp;}&lt;br /&gt;		&lt;span style="color:blue;"&gt;public&lt;/span&gt;&amp;nbsp;WebResponseTaskAwaiterSpy(&lt;span style="color:#2b91af;"&gt;MainForm&lt;/span&gt;&amp;nbsp;form)&lt;br /&gt;		{&lt;br /&gt;			&lt;span style="color:blue;"&gt;this&lt;/span&gt;.form&amp;nbsp;=&amp;nbsp;form;&lt;br /&gt;		}&lt;br /&gt; &lt;br /&gt;		&lt;span style="color:blue;"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color:blue;"&gt;bool&lt;/span&gt;&amp;nbsp;BeginAwait(&lt;span style="color:#2b91af;"&gt;Action&lt;/span&gt;&amp;nbsp;continuation)&lt;br /&gt;		{&lt;br /&gt;			&lt;span style="color:blue;"&gt;return&lt;/span&gt;&amp;nbsp;&lt;span style="color:blue;"&gt;false&lt;/span&gt;;&lt;br /&gt;		}&lt;br /&gt; &lt;br /&gt;		&lt;span style="color:blue;"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color:#2b91af;"&gt;WebResponse&lt;/span&gt;&amp;nbsp;EndAwait()&lt;br /&gt;		{&lt;br /&gt;			ButtonEnabledState&amp;nbsp;=&amp;nbsp;form.startButton.Enabled;&lt;br /&gt;			&lt;span style="color:blue;"&gt;return&lt;/span&gt;&amp;nbsp;&lt;span style="color:blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color:#2b91af;"&gt;FakeWebResponse&lt;/span&gt;();&lt;br /&gt;		}&lt;br /&gt;	}&lt;br /&gt; &lt;br /&gt;	&lt;span style="color:blue;"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color:blue;"&gt;class&lt;/span&gt;&amp;nbsp;&lt;span style="color:#2b91af;"&gt;TaskAwaiterSpy&lt;/span&gt;&amp;lt;T&amp;gt;&amp;nbsp;:&amp;nbsp;&lt;span style="color:#2b91af;"&gt;ITaskAwaiter&lt;/span&gt;&amp;lt;T&amp;gt;&lt;br /&gt;	{&lt;br /&gt;		&lt;span style="color:blue;"&gt;private&lt;/span&gt;&amp;nbsp;&lt;span style="color:blue;"&gt;readonly&lt;/span&gt;&amp;nbsp;&lt;span style="color:#2b91af;"&gt;MainForm&lt;/span&gt;&amp;nbsp;form;&lt;br /&gt;		&lt;span style="color:blue;"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color:blue;"&gt;bool&lt;/span&gt;&amp;nbsp;ButtonEnabledState&amp;nbsp;{&amp;nbsp;&lt;span style="color:blue;"&gt;get&lt;/span&gt;;&amp;nbsp;&lt;span style="color:blue;"&gt;private&lt;/span&gt;&amp;nbsp;&lt;span style="color:blue;"&gt;set&lt;/span&gt;;&amp;nbsp;}&lt;br /&gt;		&lt;span style="color:blue;"&gt;public&lt;/span&gt;&amp;nbsp;TaskAwaiterSpy(&lt;span style="color:#2b91af;"&gt;MainForm&lt;/span&gt;&amp;nbsp;form)&lt;br /&gt;		{&lt;br /&gt;			&lt;span style="color:blue;"&gt;this&lt;/span&gt;.form&amp;nbsp;=&amp;nbsp;form;&lt;br /&gt;		}&lt;br /&gt; &lt;br /&gt;		&lt;span style="color:blue;"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color:blue;"&gt;bool&lt;/span&gt;&amp;nbsp;BeginAwait(&lt;span style="color:#2b91af;"&gt;Action&lt;/span&gt;&amp;nbsp;continuation)&lt;br /&gt;		{&lt;br /&gt;			&lt;span style="color:blue;"&gt;return&lt;/span&gt;&amp;nbsp;&lt;span style="color:blue;"&gt;false&lt;/span&gt;;&lt;br /&gt;		}&lt;br /&gt; &lt;br /&gt;		&lt;span style="color:blue;"&gt;public&lt;/span&gt;&amp;nbsp;T&amp;nbsp;EndAwait()&lt;br /&gt;		{&lt;br /&gt;			ButtonEnabledState&amp;nbsp;=&amp;nbsp;form.startButton.Enabled;&lt;br /&gt;			&lt;span style="color:blue;"&gt;return&lt;/span&gt;&amp;nbsp;&lt;span style="color:blue;"&gt;default&lt;/span&gt;(T);&lt;br /&gt;		}&lt;br /&gt;	}&lt;/pre&gt;
&lt;p&gt;Both classes don&amp;#39;t actually execute the task because we know task execution works and we know it works asynchronously--we&amp;#39;re not trying to test that.&amp;nbsp; The clases return false from BeginAwait to tell the generated code that the asynchronous code &amp;quot;completed&amp;quot; (we lie).&amp;nbsp; The generated code the calls the EndAwait method to get the result of the so-called asynchronous operation.&amp;nbsp; In both cases, we get the state of the button in EndAwait.&amp;nbsp; In the case of the generic spy, we simply return a dummy--the default value for that type parameter.&amp;nbsp; In the case of the WebResponse spy, we can&amp;#39;t send back a dummy because that would be a null value and we&amp;#39;d get NullReferenceEexceptions that would abort our test.&amp;nbsp; So, we create a FakeWebResponse object and send that back that basically creates a canned response stream in memory and sends it back and that will be used in our second await.&lt;/p&gt;
&lt;p&gt;Now, we can write a unit test for startButton_Click method.&amp;nbsp; For example:&lt;/p&gt;
&lt;pre style="font-family:consolas;"&gt;	&lt;span style="color:#2b91af;"&gt;MainForm&lt;/span&gt;&amp;nbsp;form&amp;nbsp;=&amp;nbsp;CreateForm();&lt;br /&gt;	&lt;span style="color:#2b91af;"&gt;TaskAwaiterFactory&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;WebResponse&lt;/span&gt;&amp;gt;.CreateTaskAwaiter&amp;nbsp;=&amp;nbsp;task&amp;nbsp;=&amp;gt;&amp;nbsp;&lt;span style="color:blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color:#2b91af;"&gt;WebResponseTaskAwaiterSpy&lt;/span&gt;(form);&lt;br /&gt;	&lt;span style="color:#2b91af;"&gt;TaskAwaiterFactory&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;String&lt;/span&gt;&amp;gt;.CreateTaskAwaiter&amp;nbsp;=&amp;nbsp;task&amp;nbsp;=&amp;gt;&amp;nbsp;&lt;span style="color:blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color:#2b91af;"&gt;TaskAwaiterSpy&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;String&lt;/span&gt;&amp;gt;(form);&lt;br /&gt; &lt;br /&gt;	form.startButton_Click(&lt;span style="color:blue;"&gt;null&lt;/span&gt;,&amp;nbsp;&lt;span style="color:#2b91af;"&gt;EventArgs&lt;/span&gt;.Empty);&lt;br /&gt; &lt;br /&gt;	&lt;span style="color:blue;"&gt;var&lt;/span&gt;&amp;nbsp;spy1&amp;nbsp;=&amp;nbsp;&lt;span style="color:#2b91af;"&gt;TaskAwaiterFactory&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;WebResponse&lt;/span&gt;&amp;gt;.Current&amp;nbsp;&lt;span style="color:blue;"&gt;as&lt;/span&gt;&amp;nbsp;&lt;span style="color:#2b91af;"&gt;WebResponseTaskAwaiterSpy&lt;/span&gt;;&lt;br /&gt;	&lt;span style="color:blue;"&gt;var&lt;/span&gt;&amp;nbsp;spy2&amp;nbsp;=&amp;nbsp;&lt;span style="color:#2b91af;"&gt;TaskAwaiterFactory&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;String&lt;/span&gt;&amp;gt;.Current&amp;nbsp;&lt;span style="color:blue;"&gt;as&lt;/span&gt;&amp;nbsp;&lt;span style="color:#2b91af;"&gt;TaskAwaiterSpy&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;String&lt;/span&gt;&amp;gt;;&lt;br /&gt; &lt;br /&gt;	&lt;span style="color:#2b91af;"&gt;Assert&lt;/span&gt;.IsTrue((spy2&amp;nbsp;!=&amp;nbsp;&lt;span style="color:blue;"&gt;null&lt;/span&gt;&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;!spy2.ButtonEnabledState)&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;(spy1&amp;nbsp;!=&amp;nbsp;&lt;span style="color:blue;"&gt;null&lt;/span&gt;&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;!spy1.ButtonEnabledState));&lt;br /&gt;	&lt;span style="color:#2b91af;"&gt;Assert&lt;/span&gt;.IsTrue(form.startButton.Enabled);&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;This code injects our two types of awaiters (our spies), invokes the method, then checks the spies for the values we&amp;#39;re looking for as well as the current state of our button (we assume the current state at this point is the same state immediately after the asynchronous operation completed) to validate our invariants.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fmsmvps.com%2fblogs%2fpeterritchie%2farchive%2f2010%2f11%2f04%2ftesting-strategies-involving-async-functions.aspx"&gt;&lt;img src="http://dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%253a%252f%252fmsmvps.com%252fblogs%252fpeterritchie%252farchive%252f2010%252f11%252f04%252ftesting-strategies-involving-async-functions.aspx" alt="kick it on DotNetKicks.com" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1781600" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/.NET+Development/default.aspx">.NET Development</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/Software+Development/default.aspx">Software Development</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/Design_2F00_Coding+Guidance/default.aspx">Design/Coding Guidance</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/DevCenterPost/default.aspx">DevCenterPost</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/Unit+Testing/default.aspx">Unit Testing</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/TDD/default.aspx">TDD</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/C_2300_+5/default.aspx">C# 5</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/Async+Functions/default.aspx">Async Functions</category></item></channel></rss>