C#: Asynchronous Programming Basics (async/await)

Time: Column:Mobile & Frontend views:290

In UI applications such as WPF and WinForms, do not block the UI thread while waiting for asynchronous operations to complete. Instead, use the async and await keywords to keep the UI thread responsive.

In C#, asynchronous programming is a key technique for improving the performance and responsiveness of applications. This is especially important when dealing with I/O-intensive tasks such as network requests, file reading, and writing. The async and await keywords, introduced in C# 5.0, greatly simplify the asynchronous programming model, allowing developers to write asynchronous code almost as easily as synchronous code.

The async and await Keywords

  • async: This is a modifier used to mark a method that may contain asynchronous operations. Inside an async method, you can use the await keyword to wait for an asynchronous operation to complete.

  • await: This is an operator used to wait for an asynchronous operation to complete. It can only be used in methods marked with async. When you await an asynchronous operation, the current method pauses execution until the asynchronous operation finishes.

Return Types of Asynchronous Methods

Asynchronous methods can have the following return types:

  • void: Typically used for event handlers because event handlers must have a void return type. However, note that async void methods cannot be awaited, which may complicate error handling.

  • Task: Represents an asynchronous operation that does not return a value.

  • Task<T>: Represents an asynchronous operation that returns a value of type T.

Benefits of Asynchronous Programming

  • Improved application responsiveness: While waiting for asynchronous operations to complete, the application can continue to perform other tasks instead of blocking the current thread.

  • Better resource utilization: Avoids occupying valuable thread resources for extended periods.

  • Enhanced concurrency: Allows multiple asynchronous operations to run simultaneously, improving overall throughput.

Example Code

Below is a simple example that demonstrates how to use the async and await keywords for asynchronous programming:

using System;
using System.Net.Http;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        Console.WriteLine("Starting data request...");
        string content = await GetContentAsync("https://www.example.com");
        Console.WriteLine("Received data: " + content);
    }

    static async Task<string> GetContentAsync(string url)
    {
        using (HttpClient client = new HttpClient())
        {
            HttpResponseMessage response = await client.GetAsync(url);
            response.EnsureSuccessStatusCode();
            string responseBody = await response.Content.ReadAsStringAsync();
            return responseBody;
        }
    }
}

In this example, the Main method is declared as asynchronous and uses await to wait for the completion of the GetContentAsync method. The GetContentAsync method uses HttpClient to send an HTTP GET request and asynchronously reads the response content. When an asynchronous operation is awaited, the current method pauses execution until the operation is complete, and then the remaining code is executed.

Points to Note

  • Avoid blocking the UI thread: In UI applications such as WPF and WinForms, avoid blocking the UI thread while waiting for asynchronous operations to complete. Use the async and await keywords to keep the UI thread responsive.

  • Exception handling: Exceptions in asynchronous methods do not automatically propagate to the caller. Therefore, you need to use try-catch blocks within asynchronous methods to catch and handle exceptions.

  • ConfigureAwait(false): When the current synchronization context is not needed, you can use ConfigureAwait(false) to avoid unnecessary context switching, thereby improving performance.

By mastering the use of the async and await keywords, you can easily implement asynchronous programming in C#, enhancing the performance and responsiveness of your applications.