Your Ultimate async / await Tutorial in C#

Your Ultimate async / await tutorial in C#

You might have already heard about asynchronous programming or async / await, either in .Net or some other language.

In this article I will try to explain it to you, how to understand the concept easily, why and when we write asynchronous, the structure of async / await and I will include some examples to better explain the concept.

With asynchronous programming, you can divide your logic into awaitable tasks, where you can perform some long running operations such as reading a file, doing an API call, downloading a resource from web or performing a complex calculation without having to block the execution of your application on UI or service.

.Net framework gives you simple and easy to use keywords which are the async and await modifiers to transform your code from synchronous to asynchronous.

So you can call an async method separately by obtaining a task object to it, then do some unrelated work, and after that await that task, either it has already finished which will result in returning the value from the task and then using it in next statements, or if it has not finished yet, then the execution will go back to the caller of the async method, and the program will execute normally without blocking the UI or the running service, and then once the task is done, it will proceed with the rest of the async method and return.

Asynchronous Programming Patterns

There are 3 patterns for asynchronous programming: Asynchronous Programming Model (APM) pattern, Event-based Asynchronous Pattern (EAP) and the most recent one, Task-based Asynchronous Pattern (TAP).

Currently, it is recommended to only follow the Task-based Asynchronous Pattern whenever you want to have an asynchronous implementation in your application, and on top of it, you can use async / await feature to further enhance the structure of your application, making your code more organised and better maintained.

With a few slight changes on your code, you will be able to gain the benefits of asynchronous programming into your project.

Benefits of Asynchronous using async / await

The main benefits of asynchronous programming using async / await include the following:

  • Increase the performance and responsiveness of your application, particularly when you have long-running operations that do not require to block the execution. In this case, you can perform other work while waiting for the result from the long running task.
  • Organize your code in a neat and readable way significantly better than boilerplate code of the traditional thread creation and handling.
  • with async / await , you write less code and your code will be more maintainable than using the previous asynchronous programming methods such as using plain tasks.
  • async / await is the newer replacement to BackgroundWorker, which has been used on windows forms desktop applications.
  • You make use of the latest upgrades of the language features, as async / await was introduced in C# 5, and there have been some improvements added to the feature like foreach async and generalized async type like ValueTask.

Why write asynchronous?

Usually, you want to write asynchronous code for 2 different types of purposes or needs:

  • I/O bound code. This is when you want to do an input/output operation, particularly, downloading big resource from network, reading a huge file or accessing a database resouce. In this case, you use the await keyword on an async method that returns a Task or Task<T>
  • CPU bound code. This is when you want to do a heavy in-app calculation, such as calculating and displaying the remaining distance to reach the finish line of a car racing game. Image what will happen if the was done synchronously and the UI was blocked while calculating the remaining distance when the car is moving?!
    Therefore, In the CPU bound case, you use the await keyword on an async method that will be running on a background thread using the method Task.Run()

In both scenarios, your application’s UI or service’s responsiveness or running state should not be blocked or affected.

For every async method, the .Net framework will create a state machine to keep track of the calls and what should be done after the awaitable task has complete. Check this comprehensive in-depth article about async / await compilation and state machines, Also if you want to learn more about Async and what happens behind the scenes of Task and Task<T>, read Async in depth

Structure of async / await method

Turning a normal method to become asynchronous and make it use the async / await keywords, should be achieved by the following changes

  • Method definition should include the keyword async, this keyword by itself doesn’t do anything except enabling you to use the keyword await within the method.
  • Method return type should change to return either void or Task or Task<T> , where T is the return data type, so in this example it will become:

public async Task<String> GetUserNameAsync(){ }

  • By naming convention, an asynchronous method name should end with the word ‘Async’ , so if you have a method with name GetUserName, it should become GetUserNameAsync
  • When you add the keyword async to the method definition, it will enable you to use the await keyword within this method, which means you can await the method in the way you need. and if you do not include the keyword await, then the method will be treated as a normal or synchronous method.

An important note here is that even though returning void in an async method is allowed, it should not be used in most cases, as the other 2 return types Task and Task<T> represent void and T subsequently, after the awaitable method completes and returns result. So the use of void as return type should be only limited for event handlers.

Async-ready methods in .Net

There are some libraries in .Net Framework 4.5, that has a built-in support for asynchronous programming using asyncawait keywords.

These libraries, such as the HttpClient, StreamWriter, StreamReader and many more, provide you async methods that you can use in your program directly with await.

They have been added with the asyncawait capabilities because these provide functionalities that require long-running operations such as reading large file or download huge resources.

So the asyncawait will significantly improve the performance of your application while not blocking the UI or the execution.

I/O Bound async / await example

Let’s take an example for using the HttpClient’s GetStringAsync method, that will hit a provided URL and return the Http response’s html content from it and display its length on Console screen:

 CPU-bound async / await Example

Let’s take a look at this example of a CPU bound asynchronous method.

In the above program, we have added an async method, CalculateTotalAfterTaxAsync, that takes an argument of float which represents the value to calculate upon.

Inside the method, if you notice, we are awaiting a task created on a background thread. As mentioned previously, we use this methodology when we need to do some offline heavy calculation that doesn’t rely on specific I/O operation.

Once the task is completed. it will resume the CalculateTotalAfterTaxAsync with the statements after the await line. So it will displaying the Total after calculating the tax.


Microsoft has made it easy and simple to implement asynchrony in your project with the use of async / await keywords, everything happens behind the scenes, all the complexity of thread management and maintaining the state of the calls will remain shaded. So you only focus on building amazing products.

Now for any recent implementation of asynchronous, you should only use the Task-based Asynchronous Pattern and to make it even better and easier, make sure to use the keywords async / await. You will get all the benefits of asynchronous programming in addition to organizing your code and making it easier to maintain.

Leave a Reply