Async & Await
Async & Await
In order to understand what are async
& await
keywords and why we need them, Let us continue the download scenario discussed in the previous topic- In Take 2, We saw that the app does not freeze during the download, but the message telling us that the download is complete pops up even before the download is actually complete! If we need the main thread or UI thread to wait at a point in code, we need to explicitly use the await
keyword as shown below:
Take 3: Using await keyword before calling the DownloadFile()
DownloadFile()
No change to DownloadFile()
but notice that we have used async
keyword!
Bingo! This time the app and the download works as expected, without blocking UI and shows the message only after the download is complete! We have used the await
keyword just before the Task.Run()
call. This will instruct the compiler that we need to wait before moving to the next line in code, but without blocking the UI thread.
We can place the await
keyword before a Task
object or a method which returns a Task
object (we will see that shortly)
What is async?
When we add the keyword async
to the method definition, it will enable us to use the await
keyword within the method, which means we can await the method in the way we need and if we do not include the keyword await
, then the method will be treated as a normal or synchronous method! async
and await
is the newer replacement to BackgroundWorker
and other complex thread/synchronization code which had been used on windows forms and other .NET applications. It was introduced in C# 5.0.
When to use async and await ?
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 resource.
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 and so on. 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.
In both scenarios, your application's UI or service's responsiveness should not be blocked or affected.
Creating asynchronous methods
In the Take 3 code, we have called await
on a Task.Run()
. Instead of doing this everywhere this method is called, we can re-write the DownloadFile()
method in asynchronous fashion as shown below:
Take 4: Making the DownloadFile()
go async
DownloadFile()
go asyncNotice how the DownloadFile()
method is returning a Task type. You can think of a Task
as if it was a datatype!
In fact, several CPU, Network or I/O heavy .NET framework methods are written in an async fashion and their name also indicates the same - The Async suffix is included at the end. Going by that convention, we could have named the above method as DownloadFileAsync()
to let other developers clearly know that this method is designed to be used with async/await keywords.
Returning value from an async method
In Take 4, the DownloadFile()
method did not return any value to the caller. For methods that do return a value, we could use Task<T> as a return type, where T is the specific data type returned. Let’s modify the DownloadFile()
method to return a true or false based on how the download task went.
Take 5: Making the DownloadFile()
return a value
DownloadFile()
return a valueAdditional Reading
Last updated