Understanding Async in C#
What is Asynchronous code?
A lot of people seem to struggle writing asynchronous code in .NET but actually it’s quite simple. In this article I want to break it down to fundamentals and make it as easy to understand as possible.
Let’s start my thinking about the way your code executes tasks. By tasks we’re talking about the statements and method calls in your code. Typically, tasks can either be executed synchronously or asynchronously.
When we talk about asynchronous and synchronous code we’re talking about the way that a program handles multiple tasks. Synchronous code executes tasks one after the other, while asynchronous code can execute multiple tasks at the same time.
In synchronous code, each task must be completed before the next one can start. This can be visualized as a linear sequence of tasks, where each task must be completed before the next one can begin.
For example, in the following diagram, a synchronous program is executing three tasks (1, 2, and 3) in sequence. The program starts with task A, then completes task A before moving on to task B, and so on.
On the other hand, asynchronous code allows multiple tasks to be executed at the same time. These tasks can be executed in parallel, or they can be executed one after the other but with the ability to switch between them without blocking the execution of the program.
For example, in the following diagram, an asynchronous program is executing three tasks (1, 2, and 3) simultaneously. The program starts all three tasks at the same time, and the program can switch between them as needed.
So the main difference between asynchronous and synchronous code is the way that a program handles multiple tasks. Synchronous code executes tasks one after the other, while asynchronous code can execute multiple tasks at the same time. One of the main benefits of asynchronous code is that it allows for better performance, scalability, and responsiveness in certain situations, for example, when working with I/O bound operations like network calls and file operations. However, it can also make the code much more complex and harder to debug, so it's important to use it judiciously and only when it makes sense.
Using Asynchronous code in C#
In order to write asynchronous code in C# we need to use something called the async-await pattern.
The async-await pattern in allows developers to write asynchronous code that is easy to read and understand. The async keyword is used to mark a method as asynchronous, and the await keyword is used to specify that the program should wait for a task to complete before continuing. In this post, we’re going to explore the basics of the async-await pattern in and see how it can be used to improve the performance and responsiveness of your applications.
First, let's take a look at a simple example of an asynchronous method. The following code defines a method called "DelayAsync" that simulates a delay of 2 seconds using the Task.Delay method. This is a static method as we’re using this within a simple Console application:
public async static Task DelayAsync() { await Task.Delay(2000); Console.WriteLine("Delay complete."); }
In this example, the await keyword is used to tell the program to wait for the Task.Delay method to complete before continuing. The async keyword is used to mark the method as asynchronous.
Now, let's see how we can use this method in a synchronous program. The following code calls the DelayAsync method and then writes a message to the console:
public static void Main() { DelayAsync(); Console.WriteLine("Program complete."); }
When you run this program, you will see that the "Program complete." message is written to the console before the "Delay complete." message. This is because the DelayAsync method is being called asynchronously, and the program continues to execute the next line of code without waiting for the delay to complete.
To fix this, we can use the await keyword to wait for the DelayAsync method to complete before continuing. The following code shows how to do this:
public static async Task Main() { await DelayAsync(); Console.WriteLine("Program complete."); }
Now, when you run this program, you will see that the "Delay complete." message is written to the console before the "Program complete." message. This is because the program is now waiting for the DelayAsync method to complete before continuing.
In summary, the async-await pattern in C# allows developers to write asynchronous code that is easy to read and understand. The async keyword is used to mark a method as asynchronous, and the await keyword is used to specify that the program should wait for a task to complete before continuing. This pattern can be used to improve the performance and responsiveness of an application by allowing it to perform multiple tasks at the same time.
It's important to note that the await keyword can be used only inside an asynchronous method. Also, it's important to be aware of the exception handling, when an exception is thrown inside an asynchronous method, it will be wrapped in an AggregateException and it has to be handled accordingly. Look out for a post on this soon!
If you wan’t to try this out for yourself then the code is available here: https://github.com/Distinctlyminty/async-await