It has been a long time since .NET version 4.5 was released. To refresh our memory, that happened on August 15th, 2012. Yes, six years ago. Feel old yet? Well, it was not my intention to bum you out but to remind you about some of the highlights of .NET release. One of the main features that this version brought was asynchronous programming using
await methods. Basically, the guys from Microsoft made the compiler do work that developers used to do by keeping the logical structure that resembles synchronous code.
You see, back then, Windows Phone was still a thing, and making applications for these platforms had certain limitations. The main one was that Windows Phone, unlike desktop applications, introduced hard limit in which no method could block for more than 50ms. This, in turn, meant that there was no more blocking of the UI for the developers, which led to the necessity for some sort of asynchronicity in the code. .NET 4.5 represents the response to this necessity.
So, why am I writing about something that happened more than half a decade ago? Well, I noticed that even though this is an old topic, there are still a lot of engineers that struggle with the concept. To quote Mike James from iProgrammer:
Often, the programmer is fully aware that what they are doing is object oriented but only vaguely aware that they are writing asynchronous code.
That is why I will try to sum up the most important parts of this style of programming in a few blogs posts. Also, we will try to identify situations in which we should use this programming style, as well as the situations when we should avoid it. So, let’s dive right into it!
Motivation and Use Cases
Essentially, this style of programming is applicable to anywhere you need the ability to do something while waiting for something else to be complete. Years of usage of this tool have actually given us the ability to realize where we should use it. It is great for user experience, and in general for event-based systems, e.g., CPU-based parallelism or working with files.
Any activity that is potentially blocking, such as access to the web, is a good candidate for this approach. If any of these blocking activities end up in a synchronous process, the entire application is blocked. On the other hand, if this activity is a part of an asynchronous process, the application can continue working with other tasks until the activity is done.
Of course, you don’t need to abuse this ability. For example, we shouldn’t asynchronously update records that are dependent. It is generally a bad idea and our data will get out of sync very quickly. Apart from that, this concept is sometimes overused. For example, if we are working on some simple actions and operations we should consider more orthodox approaches. Using asynchronous concepts in these cases may, in fact, cause more overhead than benefits.
Async/Await and Return Types
The asynchronous mechanism is implemented in .NET by using
await keywords in our code. We use the
async operator to mark our methods as asynchronous. Only methods with this operator methods can use
await operator in them.
Await operator, on the other hand, is telling to the compiler that
async method in which it has been used can’t continue past that point until the awaited asynchronous task is complete. Basically, it suspends the execution of the method until awaited task is done. Methods that are marked with
async operator also can be called with
await operator from the other methods.
Another important thing to mention is that
async methods must return Task class or Task class. This is because in this method,
await operator is applied to the
Task that is returned from another
async method. To sum it up, the asynchronous mechanism is in .NET implemented like this:
- We use the
async operator to mark the methods that we want to be asynchronous. These methods must return Task class or Task class.
- When we are calling methods that are marked with the
async operator, we use
await operator. This operator will run the task that asynchronous method returned.
How does that look into the code? Take a look at this example WebAccess.cs class:
public class WebAccess
public async Task<int> AccessRubiksCodeAsync()
HttpClient client = new HttpClient();
var getContent = client.GetStringAsync("http://rubikscode.net");
string content = await getContent;
private void LogToConsole(string message)
Console.WriteLine("At the moment I am actually listening to the new NIN song...");
Console.WriteLine("It is pretty cool...like something of David Bowie's - Blackstar.");
Notice how we attained the structure of the synchronous code, which is awesome. Even though we are calling
await operator and essentially running asynchronous task, our code looks pretty neat and simple. This is one of the reasons why
await mechanism gained a lot of popularity.
So, what happens if
GetStringAsync method takes too long to answer? Here is how the workflow goes:
In the first step (marked with 1),
AccessRubiksCodeAsync method creates an instance of the
HttpClient and calls
GetStringAsync method of this class. The goal is to download the content of the website in a form of a
string. If something unexpected happens that blocks
GetStringAsync method, e.g., the website is taking too long to download, this method yields control to its caller. That is how it avoids blocking resources. Apart from that, this method returns
AccessRubiksCodeAsync assigns to the variable
getContent. Later in the code, this variable is used in combination with
Now, since we haven’t used await operator on
AccessRubik<wbr />sCodeAsync can continue with other operations that are not depending on the result of
getContent task. So, the
LogToConsole method can be run in a synchronous manner (step 2). This means that this method will take control, do its job and only then give control back to
After that, this method is calling
await operator (step 3). This means that at this moment, this method requires the result from
GetStringAsync method. If this
GetStringAsync is still not ready,
AccessRubiksCodeAsync is suspending its progress and returns control to its caller. Of course, bit benefit of having this kind flow is that we “gave some time” to
GetStringAsync method, and meanwhile, we have run synchronous parts of the code. When content is downloaded, its length is returned as a result (step 4).
Unit Testing Asynchronous Methods
Unit testing is actually one great example of how
async methods are initiated. In this example, I’ve used xUnit, but
await mechanism is supported in other unit testing frameworks like NUnit and MSTests. If you want to install xUnit to your project, enter these commands in Package Manager Console:
Ok, this should get you up to speed with xUnit. Now let’s take a look at our test class for
WebAccess class –
public class WebAccessTests
public async Task AccessRubiksCode_NoCondition_ExpectedResult()
var webAccess = new WebAccess();
var result = await webAccess.AccessRubiksCodeAsync();
What will happen if we do this – call the
async method without
await operator? Well, in that case, this
async method will be fired separately, and in the meantime, the calling method will continue executing. Since we didn’t
await it, you’ll never know whether and when it has completed. This can be used as an advantage in certain situations of course, but it is important to know how this mechanism is working.
Apart from that, there are no crucial changes into test structure. We are first creating an instance of
WebAccess class in “arrange” phase. In “act” phase, we are using
await operator to initiate
AccessRubiksCodeAsync method and retrieve the result. Finally, in “
assert” phase, we are checking the validity of the result.
Asynchronous programming is a somewhat standard functionality of .NET for a number of years. Still, sometimes I get the notion that less experienced programmers don’t quite get the point of it. Especially the ones that don’t have experience with some other technologies where this mechanism is directly used in the technology itself, like Node.js. Or they are familiar with it and try to use it in every situation.
In this article, I tried to explain how asynchronous programming is done in the .NET world from the high-level. In next few articles, we will go deeper into the subject and cover some other aspects of this style, as well.
Thank you for reading!