Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

C# 5.0 vNext - New Asynchronous Pattern

0.00/5 (No votes)
20 Nov 2010 2  
C# 5.0 CTP was introduced recently, this article is specally dealing with my own understanding with this realease with few sample applications
hhhhsdads


async0.JPG

Table of Contents

Introduction

Hi! As of a recent buzz around the community, after the introduction of the C# vNext in the world of .NET languages, (more precisely on C# and VB.NET) its time to let you through and understand how the features are working in current scenario. Well, it is true a large mass of people is writing about it but believe me, I didn't saw any which gives you the full example under one shot. Hence, I thought I might give it a try. In this post I will try to cover most of the bits related with Async programming model and also to give you a chance to understand the concept and give feedback on the same.

SideNote : One of my article is in monthly survey, you would like this article too.It is also present here(another) 

History

It had been a long way to go if I have to start talking about C# from the very beginning. But its quite interesting if I give you the whole shot of entire evolution of C# as a language just now before going into the latest C# adjustment. In PDC 10, Anders pointed out the entire evolution of C# language, lets go into it first :

csharpasync1.JPG

Basically C# is continuously getting enriched with newer concepts and hence gradually its becoming the industry best language but it does include backward compatibility of each of the existing language features. In the above figure, you can see, C# was introduced as a language way back in 2001 when it was first introduced as truly Managed Code language. The initial C# language was great, but had lots of things absent. Later on, C# 2.0 was introduced. It introduced with a great new feature Generics which was never introduced before. C# 3.0 was actually for LINQ, a truly language integrated query syntax, where you can dealt with querying your existing .NET data structures using simple lambdas or LINQ expressions without manually traversing the list yourself. Finally its in .NET 4.0 the Task Parallel Library was introduced, which lets you create more responsive applications by giving away Tasks for each ongoing operation.

What is TASK?

If you have used Parallel Extensions to .NET, you might already know that Task was introduced to represent the future. It represents an Ongoing operation that will result you an output in future. Task object has few features which you might address :

  • Task Scheduling
  • Establish parent child relationship between Child task to its parent
  • Implement cooperative cancellation
  • Waits can be signaled without external wait handles
  • Attach "continuation" task(s) using ContinueWith 

So task is the basic unit of Task Parallel Library which wraps up everything we need to invoke a Thread and allows to run a program module parallely.

C# 5.0 is introduced with one main motive in mind, that is to mold the language in such a way that the programmer can program the logic as he would have done synchronously maintaining the original flow of the program. C# already have Threads to deal with asynchronous kind of programming. With C# 2.0 it is very easy to write Async style of programming where you can create a Delegate and call its own implementation of BeginInvoke and EndInvoke and put a callback in, which will be called as and when the execution is done. But basically what happens, your code is getting more and more complex as you increasingly introduce more and more asynchronous patterns. You need to have callbacks for each of those calls so that when the call gets finished, the operation will finally invoke the callbacks and your rest of the logic gets executed. Thereby, with greater extent of asynchrony in your code(which we often require) your code will look more and more complex and hard to decipher for others. C# 5.0 keeps the notion of the programming model intact, but lets you write your application just as you would have done for synchronous programming style with the same logical flow and structure, but with few adjustments in your code and the work will work asynchronously.

What is TAP (Task Asynchronous Pattern)?

So if you go on with the Asynchronous pattern, in terms of Parallelism, we call the new pattern as Task Asynchronous Pattern. It is the first attempt to change the language a bit after Threads are introduced in C# 1.0 to make it easier to write truly responsive applications. By Responsive applications we mean, that we can leverage more work on one thread rather than blocking threads for UI responsiveness.

Difference between Asynchrony and Concurrency

Most of us has confusion in the concept of Asynchrony and concurrency. Well, I would say you think differently than what you think now. Lets take the example of Parallelism. If you think of concurrency we are thinking of dealing with CPU cycles. Say for instance, you want to do a big calculations for your application. In such a situation, you want to do the calculation in parallel. So what you think? You need to have multiple Threads running in parallel which finally gets you the output. Thus, if you think of a certain time in between running of your application, you actually have more than one CPU busy with your calculation and makes maximum utilization of the CPU, and concurrently accessing your resources. This is what we call Concurrency.

Asynchrony on the other hand, is a super set of Concurrency. So it includes concurrency as well as other asynchronous calls which are not CPU bound. Lets say you are saving a big file in your hard drive, or you want to download some data from the server. These things does share your CPU time-slices. But if you can do this in asynchronous pattern, it will also be included in Asynchrony.

So to summarize, Asynchrony is a pattern which yields control instantly when called, but waits the callback to arise later in future. Concurrency on the other hand, parallel execution of CPU bound applications.

Does it actually include Threads for Asynchrony?

Literally speaking, No... Its not. In present scenario, if you need to create a Responsive application you always think of creating a new Thread from the ThreadPool, calling the Resource (which eventually blocks the Thread for the moment) and finally get the result back when the device says he is ready. But does it makes sense always? No. Say you are downloading a movie, which is Network bound. So basically there is no involvement of CPU in this scenario. So according to Microsoft people, your UI Thread is actually creating the Message and thows to the Network device to do this job and returns back immediately without getting the result. The Network device will do its task accordingly (downloading the url) and finally find the UI thread using SynchronizationContext appropriately and return the result. Hence, when the Network device finishes its work, it can communicate to the appropriate thread and invoke the callback. Isnt it sounds good?

Yes, say you have 10 numbers of network calls to be made in parallel. In case of previous approach, you would have created 10 Threads each of which will call the Network API and block itself until it gets the response. Hence, even though you are not using a single time slice of CPU, all your ThreadPool threads gets exhausted. Well you might wonder, how about increasing the ThreadPool threads size? Well, you probably can, but this would give additional pressure if all the network resources gets available after a while. Hence Async pattern can help you in this regard. Such that, you would have called each of the resources asynchronousy from the same thread, and wait for the Callback to arise.

Current Async Pattern

Synchronous Block

Before I proceed what we have introduced, it is very interesting to know what is available now, so that you could compare between the two approaches. Say you want to download few links from the server, as of now I am doing it synchronously, I might use :

const string Feed = "http://www.codeproject.com/webservices/articlerss.aspx?cat={0}";
private void btnSync_Click(object sender, RoutedEventArgs e)
{
      this.SynchronousCallServer();
}
public void SynchronousCallServer()
{
        WebClient client = new WebClient();
        StringBuilder builder = new StringBuilder();

            for (int i = 2; i <= 10; i++)
            {
                this.tbStatus.Text = string.Format("Calling Server [{0}]..... ", i);
                string currentCall = string.Format(Feed, i);
                string rss = client.DownloadString(new Uri(currentCall));

                builder.Append(rss);
            }

            MessageBox.Show(
                     string.Format("Downloaded Successfully!!! Total Size : {0} chars.", 
                                      builder.Length));
}

In the above method, I have called a WebServer Url directly using WebClient and downloaded the entire string which I later on append to the builder object and finally when all the links are downloaded (sequentially) we show a MessageBox to the user. You should also notice, we are also updating a status message while downloading the urls. Now lets run our application and call the method :

sync.JPG

In the above figure you can see the application stops responding, as UI thread gets blocked when the DownloadString is called. You should also notice, the screed does not update itself with the status message, as we can see only the final status message after all the strings gets downloaded.

Asynchronous Block(The Old Way)

Now this is not a good UI design. Is it ? I say no. So let us make it asynchronous to call the download string sequentially as we are doing. So how different the code should look like:

const string Feed = "http://www.codeproject.com/webservices/articlerss.aspx?cat={0}";
private void btnaSyncPrev_Click(object sender, RoutedEventArgs e)
{
     StringBuilder builder = new StringBuilder();
     this.AsynchronousCallServerTraditional(builder, 2);
}
public void AsynchronousCallServerTraditional(StringBuilder builder, int i)
{
      if (i > 10)
      {
           MessageBox.Show(
                string.Format("Downloaded Successfully!!! Total Size : {0} chars.", 
                             builder.Length));
           return;
       }
       this.tbStatus.Text = string.Format("Calling Server [{0}]..... ", i);
       WebClient client = new WebClient();
       client.DownloadStringCompleted += (o,e) =>
       {
            builder.Append(e.Result);
            this.AsynchronousCallServerTraditional(builder, i + 1);
       }; 
            
       string currentCall = string.Format(Feed, i);
       client.DownloadStringAsync(new Uri(currentCall), null);

}

OMG! This is terrific. The code looks completely different. First of all the DownloadStringAsync of WebClient does not return the string, as the control is returned back immediately and hence to get the Result we need to add an EventHandler for DownloadStringCompleted. As the EventHandler is actually a completely different method we need to send the StringBuilder object every time to the Callback method and eventually the callback recursively calls the same method again and again to create the entire structure of data. So basically, asynchronous call to the same method looks totally different.

async1.JPG

Asynchronous Block(The New Way)

Asynchronous pattern is been simplified like heaven with the introduction of C# vNext. As shown in the PDC 10 by Anders Hejlsberg here, introduces two new keywords "async" and "await" which totally simplifies the asynchrony from the language perspective (You can also read my post which I have posted just after PDC). Before we delve into these, let me take a look at the same code in this approach:

const string Feed = "http://www.codeproject.com/webservices/articlerss.aspx?cat={0}";
public async Task AsynchronousCallServerMordernAsync()
{
    WebClient client = new WebClient();

    StringBuilder builder = new StringBuilder();
            
    for (int i = 2; i <= 10; i++)
    {
        this.tbStatus.Text = string.Format("Calling Server [{0}]..... ", i);
        string currentCall = string.Format(Feed, i);
        string rss = await client.DownloadStringTaskAsync(new Uri(currentCall));

        builder.Append(rss);
    }

    MessageBox.Show(
        string.Format("Downloaded Successfully!!! Total Size : {0} chars.", 
                  builder.Length));
}

So the code looks identically the same with two keywords "async" and "await". Does it work? Yes, when you try running the code, it works the same way as it would have done with synchronously. You have noticed that I have used DownloadStringTaskAsync, which actually an asynchronous implementation of DownloadString with the same approach. It is an extension method which will be available only if you install async CTP.

Prerequisites for Async Pattern

Asynchronous pattern is still in CTP, so you need to install few bits on your machine which will update your Visual Studio 2010 to allow these two keywords.

  • Visual Studio 2010 (No previous version supported). Try installing Express
  • Visual Studio Async CTP

After you install both of them in your machine, reference AsyncCTPLibrary which could be found in %MyDocument%\Microsoft Visual Studio Async CTP\Samples\AsyncCtpLibrary.dll to your application.

What is async and await?

Following the PDC, we can saw async is a new modifier for a method, which lets the method to return immediately after its been called. So when a method is called, the control is yielded immediately until it finds the first await. So await is a contextual keyword which might be placed before any Task (or any object which implements GetAwaiter) object which lets you to return the control back immediately while the method gets executed. Once the method gets executed the caller finds the same block and invokes a GoTo statement to the same position where we have left and registers the rest of the code as we wrote. Each of those adjustments are made automatically from the compiler itself so no user intervention is required.

How it works?

Well, compilers are good at State Machines. If you think of C# IEnumeramble, the compiler actually builds a State Machine internally for each yield statement you invoke. So when you write a logic which corresponds to a method which has yield statement in it, the whole State Machine logic is prepared by the compiler so that on a certain yield, it automatically determines the probable next yield based on the work flow. C# asynchrony builds on top of the same approach. The compiler made appropriate modifications to your program to build the complete state machine for the block. Hence, when you write await for a block it actually yields the control after calling the method, and returns back a Task object that represents the ongoing method. If the ongoing method returns something it is returned as Task<T>. Lets look at the figure below:

async2.JPG

The code runs in two phazes. First it calls AsynchronousCallServerMordern method until it finds an await, which returns a Task object immediately after registering the rest of the method in its State Machine workflow step. But after it is returned to the caller, it again invokes an await, which returns the control back to the UI (void return type in async method means call and forget). Hence the UI will be available immediately. After the call to DownloadStringTaskAsync gets finished, one time slice is taken by the program to run the existing code until it finds the next await, and it goes on until all of the links are downloaded successfully. Finally the control is free for the UI totally.

One Hidden Truth (Read to know more)

While you think of this situation, you might be thinking how is it possible to return the control before executing the whole method instance. As I didnt told you the entire fact in this regard, this type of confusion might occur to you. Let me try to clarify this a bit more.

So, when you are creating an async method, you are actually creating a new instance of the method. Methods are generally to be run. But if you think of method in real time, its the instance which runs. .NET actually cretes a statemachine object which holds different steps of the method body. If you have already used up StateMachine, you must know, state machine can easily keep track of the current state of the flow. So the method instance is nothing but the instance of a state machine, which holds the parameters, local variables, the state of the method that it is currently is. Thus when you are going to encounter the await statement, it actually saves the satemachine object as a variable which it resumes again when the awaiter gets the response.

For instance, I write the code as below :

Console.WriteLine("Before await");
await TaskEx.Delay(1000);
Console.WriteLine("After await");

Now, when you compile the assembly, it actually creates an object of StateMachine with two Method (1 for each state).

  1. It takes the First delegate and associated it with
    Console.WriteLine("Before await");
    await TaskEx.Delay(1000); 
    

    Say for instance, it names it as State 1.

  2. It takes the rest of the part to a new method.
    Console.WriteLine("After await");

So basically there is no single method body here, but the compiler creates 2 method(I will clarify those in detail just after I define TaskAwaiter) of which the first one is called first, and the object stores the current state as State1, and after a wait, when the Task Placeholder gets the appropriate result, it invokes the Next State and gives its completion.

How about Exception Handling?

How wonder, Exception Handling works the same as synchronous calls as we do for asynchronous. Prevously while dealing with async code, say for instance for WebClient.DownloadStringAsync we need to manually check for every DownloadComplete calls if e.Error has any value or not. But in case of async pattern, you can use your very own Try/Catch block to wrap around your async code and the error will be thrown automatically to catch in the block. So if you want to put the exception handling for the code you would write :

        public async Task AsynchronousCallServerMordernAsync()
        {
            WebClient client = new WebClient();

            StringBuilder builder = new StringBuilder();
            
            for (int i = 2; i <= 10; i++)
            {
                try
                {
                    this.tbStatus.Text = string.Format("Calling Server [{0}]..... ", i);
                    string currentCall = string.Format(Feed, i);
                   string rss = await client.DownloadStringTaskAsync(new Uri(currentCall));

                    builder.Append(rss);
                }
                catch(Exception ex) { 
                    this.tbStatus.Text = 
                     string.Format("Error Occurred -- {0} for call :{1}, Trying next", 
                          ex.Message, i);
            }

            MessageBox.Show(
                  string.Format("Downloaded Successfully!!! Total Size : {0} chars.", 
                        builder.Length));
        }
   

Cool. Yes it is. The async pattern does not need to do any modification to work with exceptions.

Invoking All at Once

As everything is done, you might be thinking is it not possible to invoke each of the statement parallely rather than sequentially, so that we could save some time. Yes, you are right. It is absolutely possible to deal with multiple tasks all at once and later on await for all at a time. To do this, let me modify the code :

private async void btnaSyncPresParallel_Click(object sender, RoutedEventArgs e)
{
    await this.AsynchronousCallServerMordernParallelAsync();
}

public async Task AsynchronousCallServerMordernParallelAsync()
{

    List> lstTasks = new List>();

    StringBuilder builder = new StringBuilder();

    for (int i = 2; i <= 10; i++)
    {
        using (WebClient client = new WebClient())
        {
            try
            {
                this.tbStatus.Text = string.Format("Calling Server [{0}]..... ", i);
                string currentCall = string.Format(Feed, i);
                Task task = client.DownloadStringTaskAsync(new Uri(currentCall));
                lstTasks.Add(task);
                        
            }
            catch (Exception ex)
            {
                this.tbStatus.Text = 
                   string.Format("Error Occurred -- {0} for call :{1}, Trying next", 
                              ex.Message, i);
            }
        }
    }
    try
    {
         string[] rss = await TaskEx.WhenAll(lstTasks);
         foreach(string s in rss)
            builder.Append(s);
    }
    catch {}
    MessageBox.Show(
          string.Format("Downloaded Successfully!!! Total Size : {0} chars.", 
               builder.Length));
    
}
  

So basically, what we need to do, is to create the object of WebClient inside the loop, and also need to remove the await for the DownloadStringTaskAsync call. As I have already told you that await immediately returns the control back to the caller, we do not need it to return immediately. Rather we create a list of all the Tasks and finally aggregate all the tasks into one using TaskEx.WhenAll and invoke await on that. Hence the TaskEx.WhenAll will return you an array of strings, which you might use when all the tasks finishes. OMG, the call to it is returned immediately.

Task Cancellation 

Another important part of the code is to cancel the existing ongoing task. For that, async pattern introduces a new object called CancellationTokenSource. You can make use of it to cancel an existing operation that is going on. Lets take a look at the sample application to demonstrate the cancellation.

cpsample.JPG

In this application, we have two Buttons, one of which calls Codeproject RSS feed, while the cancel button invokes the cancellation for the operation. Lets take a quick pick, how I build the application.

string url = "http://www.codeproject.com/WebServices/ArticleRSS.aspx";

CancellationTokenSource cancelToken;
private async void btnSearch_Click(object sender, RoutedEventArgs e)
{
            
    var result = await LoadArticleAsync();

    this.LoadArticleList(result);

    await TaskEx.Delay(5000);

    if (cancelToken != null)
    {
        cancelToken.Cancel();
        tbstatus.Text = "Timeout";
    }
}


private void btnCancel_Click(object sender, RoutedEventArgs e)
{
    if (cancelToken != null)
    {
        cancelToken.Cancel();
        tbstatus.Text = "Cancelled";
    }
}

void LoadArticleList(string result)
{
    var articles = from article in XDocument.Parse(result).Descendants("item")
                    let subject = article.Element("subject").Value
                    let title = article.Element("title").Value
                    let description = article.Element("description").Value
                    let url = article.Element("link").Value
                    let author = article.Element("author").Value
                    let publishdate = article.Element("pubDate").Value
                    select new Article
                    {
                        Subject = subject,
                        Title = title,
                        Description = description,
                        PublishDate = publishdate,
                        Author = author,
                        Url = url
                    };

    ICollectionView icv = CollectionViewSource.GetDefaultView(articles);
    icv.GroupDescriptions.Add(new PropertyGroupDescription("Subject"));
    this.lstArticles.DataContext = icv;

}

async Task LoadArticleAsync()
{
            
    cancelToken = new CancellationTokenSource();
    tbstatus.Text = "";
    try
    {

        tbstatus.Text = "Searching...  ";
        var client = new WebClient();
        var taskRequest = await client.DownloadStringTaskAsync(this.url);
                
        tbstatus.Text = "Task Finished ...  ";
        return taskRequest;

    }
    catch (TaskCanceledException)
    {
        return null;
    }
    finally
    {
        cancelToken = null;
    }
}

So basically, I have used a WPF application (To simplify I didn't used MVVM) where I have invoked a web DownloadStringTaskAsync call. The only thing that you need to do for TaskCancellation is to create the instance of CancellationTokenSource inside the block which you want to cancel. In the above code, I have created the object inside the method LoadArticleAsync, hence whenever I invoke cancelToken.Cancel, the await for this call will be released. You can even do calls like cancelToken.CancelAfter(2000) to cancel the operation after 2 seconds.

Going on with CPU

Last but not the least, what if, you really want to use a new Thread to call your method? With async pattern, it is even easier to do than ever before. Just take a look at the code :

private async void btnGoCPUBound_Click(object sender, RoutedEventArgs e)
{
    await new SynchronizationContext().SwitchTo();  
          //Switch to net Thread from ThreadPool

    long result = this.DoCpuIntensiveWork(); //Very CPU intensive

    await Application.Current.Dispatcher.SwitchTo();

    MessageBox.Show(string.Format("Largest Prime number : {0}", result));
}

public long DoCpuIntensiveWork()
{
    long i = 2, j, rem, result = 0;
    while (i <= long.MaxValue)
    {
        for (j = 2; j < i; j++)
        {
            rem = i % j;
            if (rem == 0)
                break;
        }
        if (i == j)
            result = i;
        i++;
    }
    return result;
}

In the above case we use SynchronizationContext.SwitchTo to get a YieldAwaitable which creates a new thread from the ThreadPool and returns an object that implements GetAwaitable. Hence you can await on the same. Later on, you can use your Dispatcher.SwitchTo to return back to the original thread again. So isn't it easy enough? Yes really, its now fun switching from one thread to another.

Things to Remember

There are quite a few things to remember in this regard, lets list them :

  1. For any async block it is important to have at least one await, otherwise the whole block will work synchronously.
  2. Any async method should postfix Async (as a rule), so your method name should look like MyMethodAsync which you put an async keyword before it.
  3. Any async method can return void(call and forget), Task or Task<T> based on the Result the await method sends.
  4. The compiler does the adjustment to find the same caller and invokes GoTo statement to execute the rest of the logic from the same position where await is invoked, rather than doing a Callback.
  5. Everything is managed by a State Machine Workflow by the compiler
  6. CPU bound calls can have its own thread, but async method does not create a new Thread by itself and blocking it waiting for the caller to arrive. Network or I/O bound calls do not involve any new Thread to be created under the hood
  7. Any object which needs to await must have GetAwaiter(even extension method) associated with it.

This is basically what you must know to deal with async pattern. In later section, I will try to go more deeper aspect of the async framework.

Getting Deeper into the Facts 

Well, it is always good to go deeper into what exactly happening with this. To check, I have used Reflector and found few interesting facts:

As I have already told you, await works only for objects which implements GetAwaiter. Now Task has the method GetAwaiter, which returns another object (called TaskAwaiter) which is used to actually register the await pattern. Any awaiter object should include basic methods like BeginAwait and EndAwait. There are quite a number of methods implemented into the library which is awaitable. Now if you look into the BeginAwait and EndAwait, its basically creating some delegates similar to what you might do in case of normal asynchronous pattern.

continuationblock.JPG

The BeginAwait actually calls TrySetContinuationforAwait, whic actually breaks apart the existing method body into two separate blocks and registers the next part of each await statement to the continuation of the Task, just like you are doing like

Task1.ContinueWith(Task2);

where Task2 represents the Rest of the code to run in callback. So if you want your object to work with asynchronous patter, you must have GetAwaiter implemented which returns an object BeginAwait and EndAwait defined. As of surprise, extension methods can also be used for writing the same for now, I am eager to see if it is possible in original version.


What about your own Bits? (CTP Only)

As in the previous section, I showed how to build an awaiter, but lets look into how our own application looks like after compiler does the trick

To demonstrate this, let me create one of the most simplest application with single await and try to demonstrate the IL of it. Lets look into the code :

public class AsyncCaller
{
    public async void GetTaskAsync(List tasks)
    {
        await TaskEx.WhenAny(tasks); 
    }
}

So, I created one class library and added this method to it. It basically awaits for any task to complete from the list of Tasks. Now if you look inside the assembly, it would look :

  public void GetTaskAsync(List tasks)
    {
        d__0 d__ = new d__0(0);
        d__.<>4__this = this;
        d__.tasks = tasks;
        d__.MoveNextDelegate = new Action(d__.MoveNext);
        d__.$builder = VoidAsyncMethodBuilder.Create();
        d__.MoveNext();
    }

There is a compiler generated type which separates the two parts of the code into two tasks and allows it to continue with the other method which is created using

VoidAsyncMethodBuilder.Create
after WhenAll retruns back the output.

   [CompilerGenerated]
    private sealed class <GetTaskAsync>d__0
    {
        // Fields
        private bool $__disposing;
        private bool $__doFinallyBodies;
        public VoidAsyncMethodBuilder $builder;
        private int <>1__state;
        public List<Task> <>3__tasks;
        public AsyncCaller <>4__this;
        private Task <1>t__$await1;
        private TaskAwaiter<Task> <a1>t__$await2;
        public Action MoveNextDelegate;
        public List<Task> tasks;

        // Methods
        [DebuggerHidden]
        public <GetTaskAsync>d__0(int <>1__state)
        {
            this.<>1__state = <>1__state;
        }

        [DebuggerHidden]
        public void Dispose()
        {
            this.$__disposing = true;
            this.MoveNext();
            this.<>1__state = -1;
        }

        public void MoveNext()
        {
            try
            {
                this.$__doFinallyBodies = true;
                if (this.<>1__state != 1)
                {
                    if (this.<>1__state == -1)
                    {
                        return;
                    }
                    this.<a1>t__$await2 = TaskEx.WhenAny(this.tasks).GetAwaiter<Task>();
                    this.<>1__state = 1;
                    this.$__doFinallyBodies = false;
                    if (this.<a1>t__$await2.BeginAwait(this.MoveNextDelegate))
                    {
                        return;
                    }
                    this.$__doFinallyBodies = true;
                }
                this.<>1__state = 0;
                this.<1>t__$await1 = this.<a1>t__$await2.EndAwait();
                Task task1 = this.<1>t__$await1;
                this.<>1__state = -1;
                this.$builder.SetCompleted();
            }
            catch (Exception)
            {
                this.<>1__state = -1;
                this.$builder.SetCompleted();
                throw;
            }
        }

Yes the CompilerGenerated nested type creates the necessary adjustment to hide the original call to BeginAwait. If you see MoveNext, you can definitely get the idea that TaskEx.WhenAny is called from there which gets the Awaiter. The Awaiter is then registered to MoveNextDelegate which stores the continuation part of the program.  Once the MoveNext finished its task it notifies using builder.SetCompleted which eventually try to call the probable next delegate (which isn't there).

Hidden Truth (Continued)...    

Now as you know that methods are not run the way we think of normally in case of async, it actually creates a StateMachine object.The VoidAsyncMethodBuilder.Create actually returns the object of the StateMachine, which internally holds each state of the method in the compiler generated sealed class. The annonymous type created holds each method into public properties, as for me d__.MoveNextDelegate is set before calling the TaskAwaiter.BeginAwait.

Thus the main thing is, when we are initially calling the method, we are actually calling the first part of the method, and after it calls BeginAwait, it eventually save the whole object in the context as a statemachine and return the control. Now when the Task has the result, it automatically invokes the EndAwaiter from itself, and the Object is again taken into account, it sees what state the object is now, and calls MoveNext accordingly(which eventually calls the next part of the method).


You should note, these kind of creating large computer generated Type will not take place in final release, but I just showed this to demonstrate the concept and also for better understanding. I would also recommend you to look into it to learn more about it.

Debugging API

Nothing much so far for Debugging, but still there is a class named DebugInfo inside System.Runtime.CompilerServices.AsyncMethodBuilder. Though the class is internal but yet you can invoke the static method ActiveMethods to get few data available for debugging such as the methods which are not yet finished, or more precisely the methods which have intermediate statemachine available in the context will be listed here.

The ActiveMethod is actually returns a List<DebugInfo> which lists :

  • StartDateTime
  • StartingThread
  • StartingExecutionContext
  • Task

When any Task is awaited, every time it builds a State Machine object which holds each step of the method body. During the initilization phaze of this, the AsyncMethodBuilder is called. In the constructor, the DebugInfo was created. If you see in reflector you will see :

debugasync2.JPG

The AsyncMethodBuilder actually adds the Task object to create a DebugInfo inside it, which is then removed when the Task completes.

debugasync.JPG

The DebugInfo actually lists only ActiveMethods while others are not browsable from Debugger.

This is basically in very priliminary stage, so I think it will add few more in later builds of Async framework.

To see those information, you can add the variable in Watch window of Visual studio and have a quick pick on those. For more details you can browse my blog post on this.

References

History

  • Initial Draft : 14th November 2010
  • 2nd Edition : Fixed image issue, and few spelling mistakes.
  • 3rd Edition : As few people told me to clarify some sections more, I made those adjustments.
  • 4th Edition: Added Debug capabilities to Async

Conclusion 

After the introduction of new Async pattern, I was thinking to learn the same by trying a few applications myself. I did everything just for fun. If I do any mistake please let me know about it. Also do give your feedback on this new pattern.

Thank you for reading

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here