The History Of Async/Await In C# (Part II)

5 min read

Async/Await: Cuộc cách mạng trong lập trình không đồng bộ với C#

Trong bài viết trước, chúng ta đã cùng nhau khám phá lịch sử của lập trình không đồng bộ và những hạn chế của mô hình APM. Hôm nay, hãy cùng tôi đến với một bước ngoặt quan trọng trong thế giới lập trình C#: sự ra đời của async/await.

Async/Await: Một phong cách mới

Async/await, được giới thiệu trong C# 5, là một cặp từ khóa mang tính cách mạng, thay đổi hoàn toàn cách chúng ta tiếp cận lập trình không đồng bộ. Với async/await, việc viết mã không đồng bộ trở nên gần gũi và dễ dàng như viết mã đồng bộ. Hãy xem qua một ví dụ đơn giản:

public async Task DownloadFileAsync(string url)
{
    using var client = new HttpClient();
    var content = await client.GetStringAsync(url);
    // ... xử lý nội dung (content) tải về
}

Trong đoạn mã trên, từ khóa async được sử dụng để đánh dấu một phương thức là không đồng bộ. Từ khóa await được đặt trước một tác vụ không đồng bộ (ở đây là client.GetStringAsync(url)), báo hiệu cho chương trình tạm dừng thực thi phương thức hiện tại và chờ đợi tác vụ đó hoàn thành. Sau khi tác vụ hoàn thành, chương trình sẽ tự động tiếp tục thực thi phần còn lại của phương thức.

Những ưu điểm vượt trội

1. Readability and Maintainability

// Async/await: Downloading multiple files
public async Task DownloadFilesAsync(string[] urls)
{
    using var client = new HttpClient();

    foreach (var url in urls)
    {
        var content = await client.GetStringAsync(url);
        // ... xử lý nội dung (content) tải về
    }
}

In this example, the code reads almost like synchronous code. The await keyword makes it clear where the code pauses to wait for the download to complete. This linear flow improves readability and makes it easier to understand the logic.

2. Simplified Error Handling

public async Task DownloadFileAsync(string url)
{
    using var client = new HttpClient();
    try
    {
        var content = await client.GetStringAsync(url);
        // ... xử lý nội dung (content) tải về
    }
    catch (HttpRequestException ex)
    {
        // Xử lý lỗi cụ thể (ví dụ: không kết nối được đến server)
    }
    catch (Exception ex)
    {
        // Xử lý các lỗi chung khác
    }
}

Error handling with async/await is as simple as using try-catch blocks, just like in synchronous code. This makes it easier to catch and handle exceptions without resorting to complex callback logic.

3. Clear Control Flow

public async Task ProcessDataAsync()
{
    var data1 = await GetData1Async();
    var data2 = await GetData2Async();

    var result = await ProcessDataAsync(data1, data2);

    await SaveResultAsync(result);
}

With async/await, the control flow is linear and easy to follow. The code reads from top to bottom, clearly showing the sequence of asynchronous operations and making it easier to reason about the program’s behavior.

4. Task Parallel Library (TPL) Integration

public async Task ProcessDataInParallelAsync(IEnumerable<string> urls)
{
    var tasks = urls.Select(url => DownloadFileAsync(url));
    var results = await Task.WhenAll(tasks);
    // ... xử lý kết quả (results) tải về từ nhiều tệp tin
}

Async/await works seamlessly with TPL, allowing you to easily parallelize tasks and achieve better performance by utilizing multiple cores or threads.

5. Hiệu suất (Performance)

Một trong những lợi ích đáng chú ý nhất của async/await là khả năng cải thiện hiệu suất của ứng dụng. Khi một tác vụ không đồng bộ được bắt đầu, luồng thực thi chính không bị chặn lại trong khi chờ đợi tác vụ hoàn thành. Điều này cho phép luồng chính tiếp tục xử lý các tác vụ khác, giúp tận dụng tối đa tài nguyên của hệ thống.

Ví dụ, trong một ứng dụng web, nếu bạn cần tải dữ liệu từ cơ sở dữ liệu và hiển thị lên trang web, việc sử dụng async/await cho phép bạn thực hiện các tác vụ này một cách đồng thời, giúp trang web tải nhanh hơn và phản hồi tốt hơn.

6. Khả năng đáp ứng

Async/await không chỉ cải thiện hiệu suất mà còn giúp tăng cường khả năng đáp ứng của ứng dụng. Khi ứng dụng có nhiều tác vụ không đồng bộ cần xử lý, việc sử dụng async/await giúp đảm bảo rằng các tác vụ này được thực hiện một cách hiệu quả, không gây ảnh hưởng đến trải nghiệm người dùng.

Ví dụ, trong một ứng dụng trò chơi, nếu bạn cần tải tài nguyên trò chơi (như hình ảnh, âm thanh) trong khi vẫn duy trì khả năng tương tác của người chơi, async/await cho phép bạn thực hiện các tác vụ này một cách song song, giúp trò chơi mượt mà và không bị gián đoạn.

7. Khả năng mở rộng (Scalability)

Async/await cũng giúp ứng dụng của bạn có khả năng mở rộng tốt hơn. Khi lưu lượng truy cập vào ứng dụng tăng lên, async/await cho phép ứng dụng xử lý nhiều yêu cầu đồng thời mà không làm quá tải tài nguyên hệ thống.

Ví dụ, trong một ứng dụng máy chủ web, việc sử dụng async/await cho phép máy chủ xử lý nhiều kết nối đồng thời mà không bị tắc nghẽn, giúp đảm bảo rằng ứng dụng luôn sẵn sàng phục vụ người dùng.

8. Tính dễ đọc và bảo trì (Readability and Maintainability)

Như đã đề cập trong bài viết trước, async/await giúp cải thiện đáng kể tính dễ đọc và bảo trì của mã. Việc sử dụng await để tạm dừng và tiếp tục thực thi mã một cách tự nhiên giúp làm rõ luồng xử lý và giảm thiểu sự phức tạp của các callback lồng nhau.

Async/Await: Không chỉ là cú pháp

Async/await không chỉ đơn thuần là một cặp từ khóa mới. Nó đại diện cho một sự thay đổi tư duy trong cách chúng ta tiếp cận lập trình không đồng bộ. Bằng cách che giấu đi sự phức tạp của các callback và luồng thực thi không đồng bộ, async/await cho phép chúng ta tập trung vào logic nghiệp vụ của ứng dụng.

Trong bài viết tiếp theo, chúng ta sẽ đi sâu hơn vào cách sử dụng async/await trong các tình huống thực tế và khám phá những lợi ích mà nó mang lại cho việc phát triển ứng dụng C#.

Hẹn gặp lại bạn trong bài viết sau!

Avatar photo

Leave a Reply

Your email address will not be published. Required fields are marked *