Async and Await Keywords in .NetCore


In .NET (and .NET Core), async and await are keywords used to implement asynchronous programming. They enable methods to execute non-blocking operations, such as performing I/O tasks or waiting for long-running operations, without freezing the application or consuming unnecessary resources.

Asynchronous Programming Introduction

  1. Non-Blocking Operations

    • Asynchronous programming allows you to perform tasks without blocking the main thread. This is particularly useful in applications with a user interface (UI) where blocking the main thread can make the UI unresponsive.

    • For example, if you are making a network request to fetch data from a server, using async and await allows the application to continue executing other tasks while waiting for the server response.

  2. Improved Performance

    • Asynchronous methods help improve the performance of your application by utilizing system resources more efficiently. Instead of waiting for a task to complete, the system can switch to other tasks, making better use of CPU cycles.

    • This is crucial for web applications where multiple requests can be handled concurrently.

Async and Await Keyword in C#

What is async?

  • The async keyword is used to declare an asynchronous method.
  • It indicates that the method contains code that may be awaited and run asynchronously.
  • An async method returns:
    • A Task if it performs asynchronous operations but returns no result.
    • A Task<T> if it performs asynchronous operations and returns a result of type T.
    • void only for event handlers.

What is await?

  • The await keyword is used to pause the execution of an async method until the awaited operation completes.
  • It ensures that the rest of the code in the method does not block the thread.
  • When the awaited task completes, execution resumes from where it was paused.

How They Work Together

  • An async method allows the use of await inside it.
  • When you use await, the method does not block. Instead, it returns control to the calling code and resumes execution once the awaited task is complete.

Benefits of async and await

Benefit Explanation
Non-blocking I/O Frees threads to handle other operations while waiting for I/O-bound tasks.
Scalability Supports high concurrency with fewer threads, improving application scalability.
Readability Simplifies asynchronous code, making it easier to understand and maintain.
Responsiveness Keeps UI or server threads responsive during lengthy operations.
Error Handling Integrates with try-catch for structured exception handling in async methods.

Example: Using async and await

Synchronous Example (Blocking)

public string GetData()
{
    Thread.Sleep(5000); // Simulate long operation
    return "Data retrieved";
}

Console.WriteLine(GetData()); // Blocks for 5 seconds

Asynchronous Example (Non-Blocking)

public async Task<string> GetDataAsync()
{
    await Task.Delay(5000); // Simulate long operation asynchronously
    return "Data retrieved";
}

public async Task ExecuteAsync()
{
    string result = await GetDataAsync(); // Non-blocking
    Console.WriteLine(result);
}

Here,

  • Task.Delay(5000) simulates a long-running task without blocking the thread.
  • The await keyword ensures that ExecuteAsync() does not block the calling thread while waiting for GetDataAsync() to complete.

Common Use Cases for async and await

1. Database Queries

var data = await dbContext.Users.ToListAsync();

2. File I/O

var content = await File.ReadAllTextAsync("file.txt");

3. Web Requests

var response = await httpClient.GetStringAsync("https://example.com");

4. Background Operations

await Task.Run(() => PerformHeavyComputation());

Example to Understand Async and Await in C#:

Please have a look at the below example. It’s a very simple example. Inside the main method, first, we print that main method started, then we call the OtherMethod. Inside the OtherMethod, first, we print that OtherMethod started and then the thread execution is sleep for 5. After 5 seconds, it will wake up and execute the other statement inside the OtherMethod method. Then it will come back to the main method, where we called OtherMethod. And finally, it will execute the last print statement inside the main method.

Example

using System;
using System.Threading;
namespace AsynchronousProgramming
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Main Method Started......");
            OtherMethod();
            Console.WriteLine("Main Method End");
            Console.ReadKey();
        }
        public static void OtherMethod()
        {
            Console.WriteLine("Other Method Started......");
            Thread.Sleep(TimeSpan.FromSeconds(5));
            Console.WriteLine("\n");
            Console.WriteLine("Other Method End");
        }
    }
}

Output

When you execute the above code, you will see that after printing OtherMethod Started……, the console window is frozen for 5 seconds. This is because here we are not using asynchronous programming. One thread i.e. the Main thread is responsible for executing the code And when we call Thread.Sleep method the current thread is blocked for 5 seconds. This is a bad user experience.

Async and Await Keywords in .NetCore

Now, let us see how we can overcome this problem by using asynchronous programming.

Async and Await Keyword

Please have a look at the below image. The Thread.Sleep() is a synchronous method. So, we have changed this to Task.Delay() which is an asynchronous method. The Task.Delay() method exactly does the same thing as Thread.Sleep() does.

And, if we want to wait for the task i.e. Task.Delay to be done, then we have to use the await operator. As we said earlier the await operator is going to release the current thread that is running from having to wait for this operation. Therefore, that thread is going to be available for all our tasks. And then after 5 seconds, the thread will be called to the place (i.e. Task.Delay()) in order to run the rest code of the OtherMethod. As we have used await keyword inside the OtherMethod, we must have to make the OtherMethod as asynchronous as using the async keyword.

It is important to realize that await does not mean that the thread will have to be blocked waiting for the operation. Await means the thread is free to go to do another thing and then he will come back when this operation (in our example Task.Dealy i.e. after 5 seconds) is done. The following example code exactly does the same thing.

Example

using System;
using System.Threading.Tasks;

namespace AsynchronousProgramming
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Main Method Started......");

            OtherMethod();

            Console.WriteLine("Main Method End");
            Console.ReadKey();
        }

        public async static void OtherMethod()
        {
            Console.WriteLine("Other Method Started......");

            //Thread.Sleep(TimeSpan.FromSeconds(5));
            await Task.Delay(TimeSpan.FromSeconds(5));
            Console.WriteLine("\n");
            Console.WriteLine("Other Method End");
        }
    }
}

Output

Async and Await Keywords in .NetCore

Now, if you run the above code, then you will see that after printing the Other Method Started when the statement Task.Dealy() executed, it will free the current thread, and then that current thread comes and execute the rest of the code inside the main method. And after 5 seconds again thread come back to the Other Method and execute the rest of the code inside the SomeMethod.


Prev Next

Top Articles

  1. What is JSON
  2. How to convert a javaScript object in JSON object
  3. Some Important JSON Examples
  4. Common JSON Interview Question