Async and Await in C#

Introduction

You might have already come across this Asynchronous word or an Asynchronous concept in .NET or any other programming language. In this article, I’ll try to explain the concept in an easy way. I’ll try focusing on What is Asynchronous and why we use it and in what type of situations it is more useful and the structure of async and await with some basic example to understand.

Before getting into details, we define what is synchronous and asynchronous metaphorically in the real world.

Synchronous

A person writing a program is known to be Synchronous. (What you do normally)

Asynchronous

A person is writing a program, listening to music, and also chatting with a group online. This way of doing multiple tasks at a time is known as Asynchronous. (Doing multiple tasks without affecting other ones)

What is Asynchronous Programming?

If a programmer wants to run some part of the code separately from the main thread execution, he will make use of this Asynchronous Programming.

.NET Framework has given us these keywords, async and await to transform our code from synchronous to an Asynchronous way of doing things.

What Async keyword actually does?

We prefix an async Keyword to a method in this way:

async Void Example(){…}

After using this async keyword, if a programmer wants to call asynchronous tasks, he needs to use the await keyword. What it's telling us is, (Hey! I’m an async, to make use of me in a program you need to use my name async in a method and to call me, you need to use my friend await)

What is await?

The keyword await means waiting for an event to happen.

What are the benefits of Asynchronous Programming?

You might have come across some applications online which are some times unresponsive and takes more time to load than usual. Have you ever wondered for what reason an application must load for such a long time? Well, obviously the application is trying to execute tasks behind other particular tasks, which takes a long time than usual. Because of this, other tasks need to wait, which is known as a synchronous way of doing things, such as one after the other. Then, here comes the need for Asynchronous programming, which increases the throughput and responsiveness of the application. Even though there will not be a drastic change in time taken to finish the task between synchronous and asynchronous, while in an asynchronous call, a thread is not blocked from responding to other requests.

Why use Async?

If you want to do input/output operations like downloading a large resource or reading it from the network, we use await keyword on an async method, which returns a Task or Task<T>. I hope you are aware of Task<T>. If not, you can find more about it here.

Asynchronous in .NET uses only three return types:


  • Task

  • Task<T>

  • Void


What is Task and Task<T>?

The task does not return a value and represents only a single operation.

Task<T> is a return value of Type T and represents only a single operation.

Void does not return a value.

Task and Task<T> is promising us that the work will be finished at a later point.

If an exception occurs inside the asynchronous method with a return type of Task or Task<T>, the exception details are stored inside the Task instance.

It is recommended not to use void with asynchronous, since if an exception occurs inside an asynchronous method with a return type of void, the exception details are stored inside SynchronizationContext. This will be active and we cannot handle exceptions raised in this method using void or with exception handlers because of different error handling semantics. Learn more about the best practice in asynchronous programming here.

Synchronization is about tasks, whereas threading is about workers.

Is Asynchronous Multi-Threading?

No, Asynchronous is not multithreading because multithreading works on separate threads with no interaction between them, whereas in asynchronous, threads leave and return at some point while in execution. To resume this execution at some point it has to be stored on something, and to store .NET uses a SyncronizationContext (It represents a location where code might be executed).

What is I/O Bound and CPU Bound in async?

In asynchronous, I/O bounds are tasks that require a response from outside sources like services, APIs, etc., our processor waits for these services to finish their tasks and respond.

CPU bounds are operations in which computations can be performed on a separate thread so that the main thread can continue its execution.

Patterns in Async

Async is comprised of three patterns:


  • Asynchronous Programming Model

  • Event-based Asynchronous Pattern

  • Task-based Asynchronous Pattern


It is recommended to use Task-based Asynchronous Pattern (Tap)

Structure of async and await

A keyword async should be used in a method. This async keyword alone does nothing unless and until you use an await keyword.

There should be a return type to this method like Task or Task<T> or void

For example:

public async Task<string>ExampleAsync(){}

Note

Asynchronous method name should end with Async word, so if you are having a method Doctor it should end with DoctorAsync and if you do not use the keyword await, this will work just as a normal synchronous method.

.NET Framework 4.5 has some libraries with built-in support for Asynchronous programming with the help of async and await keywords, such as HttpClient, StreamReader, and StreamWriter. We can use these methods directly using the await keyword.

Example program on async and await using HttpClient:

using System;    
using System.Threading.Tasks;    
using System.Net.Http;    
 
namespace ExampleApp   
{    
 class Program    
        {    
 private const string URL = "https://www.c-sharpcorner.com/";    
 
 static void Main(string[] args)    
            {    
                DoingSynchronous();    
                var MultiTask = MultipleTasksAsync();    
                DoingSynchronousAfterAwait();    
                MultiTask.Wait();    
                Console.ReadLine();    
            }    
 public static void DoingSynchronous()    
            {     
                Console.WriteLine("Writing a program");    
            }    
 
 static async Task MultipleTasksAsync()    
            {    
                Console.WriteLine("Doing Multiple tasks at a time ");    
                await GetURLAsync();    
            }    
 
 static async Task GetURLAsync()    
            {    
 using (var httpClient = new HttpClient())    
                {    
                    Console.WriteLine("Waiting for GetURLAsync to happen");    
 string output = await httpClient.GetStringAsync(URL);  
                    Console.WriteLine($"\n OK! awaiting has finished \n The length of {URL} is {output.Length} characters");    
                }    
            }    
 static void DoingSynchronousAfterAwait()    
            {    
                Console.WriteLine("Mean While I'm doing some other work");    
 for (var i = 0; i <= 3; i++)    
                {       
                    Console.Write("I'm Updating the Weather Info \t");    
                }    
 
            }    
        }    
}    


Conclusion

Use asynchronous keywords when you're doing something that does not involve user Interface. Asynchronous programming increases the responsiveness and throughput of the application. Asynchronous deals with application throughput, which means the performance of tasks is through the computing service but not the application performance itself because throughput is a way of measuring performance. Beware of improper use of async void, since the compiler will not warn us about it. Use the Task-based asynchronous pattern for any asynchronous programming implementation.


Source:Paper.li

Recent Posts

See All

Python 3 Network Packet Sniffer

A simple pure-Python network packet sniffer. Packets are disassembled as they arrive at a given network interface controller and their information is displayed on the screen. This application maintain