Click here to Skip to main content
13,901,218 members
Click here to Skip to main content
Add your own
alternative version

Tagged as

Stats

5.3K views
2 bookmarked
Posted 22 Feb 2015
Licenced CPL

Internal Implementation of Async Methods in .NET [#2]

, 22 Feb 2015
Rate this:
Please Sign up or sign in to vote.
Internal Implementation of Async Methods in .NET [#2]

The State Machine in Async

Previously [Part 1] The Stub Method of Async

The state machine does exactly what it is supposed to – keeps track of the state when the execution reaches await. When await is reached, everything about where we are in the method is preserved, so that it can be resumed when the method is awaiting.

Instead of copying all local variables, which could potentially result in a lot of generated code, the compiler changes all the local variables to member variables and stores the instance of the type. Obviously, in case of static async methods, there is no instance, so it would be omitted. The state machine is generated as an inner struct nested under the type, giving it access to the private members of that type.

Below is the example of what member variables would be generated for <GetStringAsync>d__0:

public int <>1__state;
public AsyncTaskMethodBuilder<string> <>t__builder;
public AsyncStringClass <>4__this;
public string value;
public string <result>5__1;
private TaskAwaiter <>u__$awaiter2;
private object <>t__stack;

Description of Member Variables

The <>1__state variable to store the await count we have reached. Initially, before any await is reached, its value is -1. Each await in async method is numbered and the number of the current await is written to this member variable.

Next is the <>t__builder, which is helper type containing the logic that all state machines share. It creates the Task that is returned by the method. The Task is created similarly to how you would create a Task from TaskCompletonSource. The only difference here is that it is optimised for async methods and is implemented as a struct for performance reasons. If you are also curious about the implementation details of AsyncTaskMethodBuilder the source code, again can be found here.

You would notice that this file contains some other helper types.

The <>__this variable contains the object that contains our async method. For static async methods, this variable will not be generated (as stated previously). The knowledge of the type will suffice. After the async transformation, it needs to be stored and the code would have moved away from its original method and the object.

The value variable is nothing more than the reference to our string (I almost wrote a ‘copy of our string’ here). All accesses to our value method parameter will be replaced by value stored in the generated struct.

Exactly the same logic applies to the result method variable, which is stored in the struct as <result>5__1.

The variable <>u_$awaiter2 is a variable of type TaskAwaiter. It is used as a temporary storage for the object that is used by the await keyword to sign up for notification when the Task finishes.

Finally note, that the state machine keeps track of the stack in the member variable <>t__stack. All the current values are placed in this variable. If there is more than 1, then the values are placed inside a Tuple.

License

This article, along with any associated source code and files, is licensed under The Common Public License Version 1.0 (CPL)

Share

About the Author


You may also be interested in...

Comments and Discussions

 
GeneralMy vote of 5 Pin
Thomas Maierhofer (Tom)23-Feb-15 1:31
memberThomas Maierhofer (Tom)23-Feb-15 1:31 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web02 | 2.8.190306.1 | Last Updated 22 Feb 2015
Article Copyright 2015 by Elliot Balynn
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid