# To await or not - C# and asynchronous programming

Since the introduction of *async/await* in C# 5 (2012), new developers still struggle to understand how it works and when to use it. I have conducted numerous interviews in which even experienced developers have struggled to explain how *async/await* works. In this article, I will try to explain what is *async/await*, how it works, how to use it and what to avoid when using it.

In C#, the *await* keyword is used to asynchronously wait for a task to complete. When an asynchronous method is called, it returns a task that represents the ongoing work. The *await* keyword, when encountered, allows returning control to the calling method while the called method continues executing the task. Once, the *awaited* task is complete, the calling method continues to run the code following the *awaited* method call.

On the face of it, it seems as though a new thread to run the *awaited* method is created because how can control be returned to the caller if the same thread is being used? This misconception catches both new and experienced developers. One critical idea to understand is that *async*/*a*wait is aimed at I/O tasks. In synchronous programming, it means the calling thread is blocked and waits for the result of the I/O operation. Using *await* means that the calling thread does not have to be blocked and can be used for other tasks too while waiting for the I/O task result. Under the hood, a state machine is created that then allows execution to continue after the *awaited* task is complete. I will not go into details about the state machine but you can read [a good article here](https://devblogs.microsoft.com/premier-developer/dissecting-the-async-methods-in-c/).

*Async/await* provides a cleaner way of writing asynchronous code. Before *async/await*, C# developers had other ways of achieving asynchronous programming including background worker, threads and Task Parallel Library (TPL). The *async* keyword is used to mark a method as asynchronous. A method marked as *async* must always return a Task or Task&lt;T&gt;. A caller of this method can use the *await* keyword in front of the method call. Let's look at an example to make this concrete:

```csharp
public async Task<string> GetDataAsync()
{
    using (HttpClient client = new HttpClient())
    {
        var response = await client.GetAsync("https://api.example.com/data");
        return await response.Content.ReadAsStringAsync();
    }
}

private async Task PrintData()
{
    var data = await GetDataAsync();
    Console.WriteLine(data);
}
```

In the above code snippet, when *PrintData* calls *GetDataAsync*, the control flow returns to the caller of *PrintData* while *GetDataAsync* is executing. The code after the call to *GetDataAsync* does not execute. However, once *GetDataAsync* completes executing, *PrintData* then continues to execute the rest of the code in the method. Notice that, the call to *GetDataAsync* is non-blocking but that does not mean the code after the call to *GetDataAsync* will execute before the task completes.

Using *await* has several benefits. First, it allows for more efficient use of resources. When a method is *awaited*, the calling code can continue executing, rather than being blocked until the task completes. This can lead to a significant boost in performance, especially when working with I/O-bound operations such as network or file access.

Another benefit of using *await* is that it makes asynchronous code easier to read and understand. Without *await*, asynchronous code can easily become complex and difficult to follow, with multiple levels of nested callbacks. By using *await*, the code can be written more linearly and predictably, making it easier to debug and maintain.

However, there are scenarios where it might not be appropriate to use *await*. For example, if an operation is expected to complete immediately, using *await* might add unnecessary overhead. In these cases, it might be better to simply use synchronous code.

Additionally, if an application requires a high degree of parallelism, it might be more appropriate to use the Task.Run method to run operations in parallel, rather than using *await*. Let's look at the example below. Notice that *CalculateTotal* awaits the *Calculate* method. There are several issues with this code. First, the operations in Calculate are non-complex and the method will likely return immediately.

```csharp
public async Task<decimal> Calculate(int quantity, decimal price)
{
    decimal subtotal = quantity * price;
    decimal total = subtotal += subtotal * VAT_CONST;
}

private async Task CalculateTotal(int quantity, decimal price)
{
    decimal total = await Calculate(quantity, price);
    Console.WriteLine(total);
}
```

Using *await* in this scenario is most likely to create more overheads than using synchronous code. Remember that a call to *await* will result in a state machine that keeps track of the state of each awaited task.

The second issue with the above code is that *Calculate* is a CPU-bound task. The method is still consuming CPU cycles and *await* offers no benefit here. In many cases where code is written this way, the developer's intention is usually to run the task in the background. In such a scenario, Task.Run may be more suitable.

In general, whether to use *await* or not depends on the specific requirements of the task and the nature of the operations being performed. For I/O-bound operations, *await* is generally recommended to improve performance and readability. For CPU-bound operations, it may be more appropriate to use synchronous code or the Task.Run method.
