Asynchronous programming is a programming model that allows you to write code that can run concurrently without blocking the main thread.
To better understand this definition, let’s talk about a real-world example.
Picture yourself uploading a file to Google Drive. Depending on the size of the file, the amount of time it takes to complete the upload can vary. While you’re waiting, you can make use of your time by browsing the internet or watching a video on your phone. This is similar to how async programming works – it enables your computer to initiate a task and continue performing other operations while it’s waiting for the task to complete.
This means that with asynchronous programming the performance and responsiveness of your application ca be greatly improved, especially when dealing with slow or blocking operations, such as I/O or network operations.
There are many benefits of using asynchronous programming in C# and some of the benefits include:
- Responsiveness – One of the main benefits of using asynchronous is that it allows you to write code that can run concurrently without blocking the main thread. This means that the application will be way more responsive than when the main thread is blocked.
- Simplicity – Another benefit of asynchronous programming is that it simplifies the code. The code is easier to read, write, and maintain, especially when compared to traditional asynchronous programming techniques, such as callbacks or manual thread management.
- Performance – By using asynchronous programming you can write code that can run concurrently and take full advantage of multi-core processors, leading to improved performance and scalability.
C# provides the async
and await
keywords to simplify asynchronous programming.
async
is used to declare a method as asynchronous. await
is used to wait for a task to complete before moving on to the next line of code. It essentially suspends the execution of the method until the awaited task is complete. When the task is complete, the method resumes execution where it left off.
async
and await
is especially useful when it comes to operations that are time-consuming like I/O operations, database operations, HTTP requests, and more. Below there are some examples that might help you better understand async and await usage.
Example 1 – Async method that performs an I/O operation
using System.IO; using System.Threading.Tasks; public async Task<string> ReadFileAsync(string filePath) { using (var reader = new StreamReader(filePath)) { return await reader.ReadToEndAsync(); } }
In this example, the ReadFileAsync
method is an asynchronous method that performs an I/O operation. The method uses the await
keyword to wait for the ReadToEndAsync
method to complete, which reads the entire contents of a file. The method returns a Task<string>
that represents the asynchronous operation and its result.
Example 2 – Async method that performs an HTTP request
using System.Net.Http; using System.Threading.Tasks; public async Task<string> GetDataAsync(string url) { using (var client = new HttpClient()) { return await client.GetStringAsync(url); } }
In this example, the GetDataAsync
method is an asynchronous method that performs an HTTP request. The method uses the await
keyword to wait for the GetStringAsync
method to complete, which performs an HTTP GET request and returns the response as a string. The method returns a Task<string>
that represents the asynchronous operation and its result.
Example 3 – Async method that performs a database query
using System.Data.SqlClient; using System.Threading.Tasks; public async Task<int> GetCountAsync(string connectionString) { using (var connection = new SqlConnection(connectionString)) { await connection.OpenAsync(); using (var command = new SqlCommand("SELECT COUNT(*) FROM MyTable", connection)) { return (int)await command.ExecuteScalarAsync(); } } }
In this example, the GetCountAsync
method is an asynchronous method that performs a database query. The method uses the await
keyword to wait for the OpenAsync
and ExecuteScalarAsync
methods to complete, which opens a connection to a database and executes a query that returns a scalar result. The method returns a Task<int>
that represents the asynchronous operation and its result.
The examples above demonstrate how async
and await
can be used to simplify and improve the performance of asynchronous programming in C#.
Image by ArthurHidden on Freepik