Last Updated on April 22, 2018 by Aram
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 likeforeach async
and generalized async type likeValueTask
.
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 aTask
orTask<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 theawait
keyword on an async method that will be running on a background thread using the methodTask.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 keywordawait
within the method. - Method return type should change to return either
void
orTask
orTask<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 becomeGetUserNameAsync
- When you add the keyword
async
to the method definition, it will enable you to use theawait
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 async
/ await
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 async
/ await
capabilities because these provide functionalities that require long-running operations such as reading large file or download huge resources.
So the async
/ await
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.
Conclusion
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.
What a well written article!
Thank you, nice article .