CodeDigest.Com Logo
Featured:

Learn Asynchronous Programming (async, await) in C# in 10 Minutes

Asynchronous programming model is simplified so much with the release of .NetFramework 4.5 which introduced async and await keywords. Prior to this, the .NetFramework had support for asynchronous programming but it was too complicated to understand and implement. Initially, there was a paradigm called Asynchronous Programming Model (referred as APM) which exposed long running framework API methods with pair of begin and end methods. For example, in .NetFramework 2.0, the ADO.Net ExecuteReader() method has a APM counterparts methods BeginExecuteReader() and EndExecuteReader(). Similarly, there was another methodology called Event-based asynchronous pattern (EAP) which approached asynchronous model as event based model. For example, there was an asynchronous method called WebClient.DownloadStringAsync with an associated event  WebClient.DownloadStringCompleted for downloading webpage contents. Though, these approaches worked well but they are not easier to implement. Let’s see how async and await helps us to implement asynchronous methods in a more simpler way.

How to use async and await for Asynchronous Programming?

The biggest advantage of using async and await is, it is very simple and the asynchronous method looks very similar to a normal synchronous methods. It does not change programming structure like the old models (APM and EAP) and the resultant asynchronous method look similar to synchronous methods. The compiler takes the complexity part and takes care of everything when we use async and await for asynchronous methods.

Asynchronous method Definition

  1. An async method is represented by using async modifier in the method signature.

  2. If the method has any return types they are enclosed as part of Task<TResult> object.

  3. If the method does not return any values then the return type is just Task. Void is also a valid return type and it is used for asynchronous event handlers.

  4. Every async method should include at least one await operator in the method body to take the advantage of asynchronous programming.

It is a recommended practise to name the asynchronous methods with ending string as Async (WriteAsync(), ReadAsync()). Let’s move ahead and implement a very simple method to demonstrate asynchronous methods.

Example:

Let’s build a simple async methods that greets us with a welcome message. For simplicity, we will just simulate a long running process inside the asynchronous method using Task.Delay(). Include System.Threading.Tasks namespace for writing asynchronous methods.

 

public async static Task GreetAsync()
{
    Console.WriteLine("Async Application Started!");
    
    //Call Async method
    Task<string> greetMsg = GetGreetingsAsync();

    //Do your other stuffs synchronously while async method is in progress            
    Console.WriteLine("Async Method in started....");

    Console.WriteLine("Current Time: " + DateTime.Now);
    Console.WriteLine("Awaiting result from Async method...");

    //All work completed, wait for async method to complete
    string msg = await greetMsg;

    //Print Async Method Result
    Console.WriteLine("Async method completed!");
    Console.WriteLine("Current Time: " + DateTime.Now);
    Console.WriteLine("Async method output: " + greetMsg.Result);

    Console.WriteLine("Async Application Ended!");
    Console.Read();
}
public async static Task<string> GetGreetingsAsync()
{
    //simulate long running process
    await Task.Delay(10000);
    return "Welcome to Async C# Demo!";
}
 

As you can see, the asynchronous methods are decorated by using async modifier. When the request arrives and the GreetAsync() method is called, the asynchronous call is made when the compiler calls GetGreetingsAsync() method.

 

Task<string> greetMsg = GetGreetingsAsync();

 

This method(GetGreetingsAsync()) represents (actually simulates) a thread blocking operation or an I/O call which can make the current thread to potentially wait if it is synchronous method. For easy understanding, i will just make a delay of 10 seconds by calling Task.Delay(). Since, they are async methods, the compiler calls the method and returns a Task<string> object without waiting for its completion. For now, let’s just forget the await in GetGreetingsAsync() method which is used to just simulate a thread blocking process like reading a file in network share. The Task<string> object represents an ongoing asynchronous task that will return a string value on completion. This means, the current thread that calls the GetGreetingsAsync() returns without waiting and continues to execute subsequent lines of code after this method call synchronously. In the above code, it prints current datetime and executes next statement that prints “Async Method in started....” while the async method GetGreetingsAsync() is still executing.

When the thread subsequently executes the next line which has await operator(await greetMsg), the thread suspends its execution and it is returned to the method that called GreetAsync() or it is placed back into the thread pool if it is the top method(like Controller Action or Button click event handler in windows app) until the called async method(GetGreetingsAsync()) completes it execution and returns. The await operator hints that the code after this point requires the output of the async method that is still executing and cannot continue untill it finishes.

 

string msg = await greetMsg;

 

It is here the benefit of using asynchronous methods are taking place. The threads that is returned to the thread pool is available for other requests for processing. If it is a synchronous method the thread will be busy waiting without doing anything. Once the asynchronous method completes the execution, the async methods updates the state to Task object marking it completed and the string value is returned to msg variable. Now, when the string greetMsg value is returned, a new thread from the thread pool is dispatched and executes the subsequent lines of code in the method. This means, the thread that called the async method and the thread that does the remaining execution may be different.

This process is repeated for multiple nested async method calls and the thread is returned to callee or thread pool instead of just waiting for blocking operation to complete. In our example code, the first method GreetAsync() is itself an asynchronous method, so the await will return the thread to the main method that called GreetAsync().

When executed you will get output like below,

After printing the Current Time (first occurrence in the above output) it waits for the async method to complete. You can see the start and end timestamp (squared) has 10 second delay before and after async method completion. During this waiting time the thread will be available for other request processing.

Note – The above method can be called from Main() method like below. Without calling Wait() the main method will exit without waiting for async method to complete.

 

static void Main(string[] args)

{

   GreetAsync().Wait();

}

 

 

What an Asynchronous method not do?

The asynchronous method does not create new thread to run the method. The asynchronous methods runs on the current synchronization context and uses the time on the calling thread. It is beneficial when there is a blocking operations like calling a web service, reading a file, reading a website page that blocks current thread.

An async method cannot declare ref or out parameters, but it can call methods that have ref or out parameters.

Advantages

  1. Using asynchronous methods increases the responsiveness of the application. For example, in a desktop application when the compiler awaits a blocking operation in an asynchronous event handler, the application UI will still respond to user actions like resize, minimizing, etc since the UI thread is returned back. In an synchronous application, this will freeze the window as if the application stopped responding. This is because the UI thread will be waiting for the blocking operation to complete and the app UI will not respond to any user actions.

  2. Helps in application scaling in server based application. When await is encountered in Asp.Net application, the thread is returned to the thread pool for other request to use the thread. In synchronous method, the thread will be waiting for the blocking operation to complete. When the number of concurrent request increases and if all threads were waiting then the application will throw 503 (Service unavailable) or when the waiting request queue limit exceeds it will throw 503 status (Server Too Busy)

Async Methods in Base Class Library

.Net Framework Base Class libraries already have some useful asynchronous methods in some of the in-built classes. Some commonly used classes are,

  1. HttpClient

  2. Stream, StreamWriter, StreamReader, XmlReader

Happy Learning!!