0
0
Lập trình
Thaycacac
Thaycacac thaycacac

Hướng Dẫn Hiểu Async/Await Trong C# Cho Người Mới Bắt Đầu

Đăng vào 2 tuần trước

• 5 phút đọc

Hướng Dẫn Hiểu Async/Await Trong C# Cho Người Mới Bắt Đầu

Nếu bạn mới bắt đầu với C#, chắc hẳn bạn đã thấy asyncawait trong các đoạn mã hiện đại và tự hỏi:

  • Chúng thực sự làm gì?
  • Chúng có tạo ra các luồng mới không?
  • Tại sao chúng ta cần chúng?

Hãy cùng tìm hiểu một cách đơn giản.

Lập Trình Asynchronous Là Gì?

Thông thường, mã C# chạy đồng bộ => một dòng sau một dòng.

csharp Copy
var data = GetData();
ProcessData(data);
ShowResult();

Nếu GetData() mất 5 giây, mọi thứ khác sẽ chờ cho đến khi nó hoàn tất, điều này có thể khiến ứng dụng của bạn cảm thấy bị đóng băng.

Lập trình bất đồng bộ cho phép bạn nói => Hoàn thành công việc này trong nền, và khi bạn xong, hãy quay lại và cho tôi biết.

Với cách này, ứng dụng có thể tiếp tục phản hồi trong khi chờ đợi các thao tác chậm (như gọi API, nhập/xuất tập tin, hoặc truy vấn cơ sở dữ liệu).

Task Là Gì?

Trong C#, một Task giống như một hứa hẹn về một thao tác trong tương lai.

  • Một Task có nghĩa là “Tôi sẽ cho bạn một số nguyên… sau.
  • Một Task (không có loại) có nghĩa là “Tôi sẽ hoàn thành một số công việc… sau.

Ví dụ:

csharp Copy
public Task<int> GetNumberAsync()
{
    return Task.Run(() =>
    {
        Thread.Sleep(1000);
        return 42;
    });
}

Khi bạn gọi GetNumberAsync(), bạn không nhận được ngay lập tức số 42. Bạn nhận được một Task sẽ cuối cùng chứa số 42.

async Làm Gì Trong Trường Hợp Này?

Từ khóa async đánh dấu một phương thức là bất đồng bộ. Nó cho phép bạn sử dụng từ khóa await bên trong nó, tức là cho phép bạn gọi các phương thức bất đồng bộ trong mã của bạn trong trường hợp cần kết quả để tiếp tục.

csharp Copy
public async Task<int> GetNumberAsync()
{
    await Task.Delay(1000);
    return 42;
}

Tại đây, await Task.Delay(1000) nói: “Dừng lại ở đây, để mã khác chạy, và quay lại sau 1 giây.

await Làm Gì?

await là từ kỳ diệu. Nó nói với C#: “Dừng lại ở đây cho đến khi Task hoàn tất, nhưng đừng chặn luồng. Hãy để công việc khác tiếp tục trong khi chờ đợi.

csharp Copy
public async Task RunAsync()
{
    Console.WriteLine("Bắt đầu...");
    var result = await GetNumberAsync();
    Console.WriteLine($"Kết quả: {result}");
}

// #output#
// Bắt đầu...
// (tạm dừng 1 giây)
// Kết quả: 42

Nếu không có await, bạn chỉ nhận được một đối tượng Task, không phải kết quả.

Async/Await và Luồng

Đây là nơi mà nhiều người mới bắt đầu gặp khó khăn:

  • Async/await có tạo ra các luồng mới không?
  • Có phải là đa luồng không?

Câu trả lời ngắn gọn: Không, không trực tiếp.

Async/await liên quan đến công việc bất đồng bộ, không phải tạo ra các luồng.

Hầu hết các thao tác bất đồng bộ (như đọc một tập tin, gọi một API web, hoặc ghi vào cơ sở dữ liệu) sử dụng các tính năng của hệ điều hành mà không cần một luồng riêng biệt trong khi chờ đợi.

Nếu bạn thực sự muốn một luồng mới, bạn sử dụng ví dụ như Task.Run().

Ví dụ:

csharp Copy
public async Task FetchAndShowDataAsync()
{
    Console.WriteLine("Đang lấy dữ liệu...");
    var data = await GetDataFromApiAsync(); // không chặn
    Console.WriteLine($"Nhận được: {data}");
}

Ngay cả khi API mất 2 giây, ứng dụng của bạn không bị chặn; nó vẫn có thể xử lý đầu vào từ người dùng, thực hiện các tác vụ khác, hoặc phục vụ các yêu cầu.

Thực Hành Tốt Nhất Khi Sử Dụng Async/Await

  1. Tránh sử dụng async void: Chỉ nên sử dụng async void cho các sự kiện. Đối với các hàm khác, hãy sử dụng async Task để dễ dàng quản lý lỗi và chờ đợi.
  2. Sử dụng Task.WhenAll: Nếu bạn cần thực hiện nhiều Task cùng một lúc, hãy sử dụng Task.WhenAll() để chờ tất cả hoàn tất.
  3. Thực hiện xử lý lỗi: Sử dụng try/catch để xử lý các lỗi có thể xảy ra trong các phương thức bất đồng bộ của bạn.

Các Cạm Bẫy Thường Gặp

  1. Quên từ khóa await: Nếu bạn quên thêm await vào một Task, nó sẽ không hoạt động như mong đợi và có thể gây ra lỗi logic.
  2. Xử lý lỗi không đúng cách: Không kiểm tra các lỗi trong Task có thể dẫn đến việc ứng dụng của bạn gặp sự cố.

Mẹo Tối Ưu Hiệu Suất

  • Tránh tạo Task không cần thiết: Chỉ tạo Task khi thực sự cần thiết, như khi gọi API hay thực hiện các tác vụ lâu.
  • Sử dụng CancellationToken: Nếu bạn có thể hủy bỏ một tác vụ đang chạy, hãy sử dụng CancellationToken để quản lý tốt hơn.

Giải Quyết Vấn Đề

  • Nếu ứng dụng không phản hồi: Kiểm tra xem bạn có đang sử dụng await đúng cách không và đảm bảo không có mã nào chặn luồng chính.
  • Nếu không nhận được kết quả mong đợi: Đảm bảo rằng các phương thức bất đồng bộ của bạn đang hoạt động như mong đợi và không bị lỗi.

Kết Luận

Việc hiểu cách hoạt động của asyncawait trong C# là rất quan trọng để xây dựng các ứng dụng hiệu suất cao và thân thiện với người dùng. Hãy thử nghiệm với các ví dụ mà chúng tôi đã cung cấp và áp dụng vào dự án của bạn. Nếu bạn có bất kỳ câu hỏi nào, đừng ngần ngại để lại câu hỏi bên dưới!

Câu Hỏi Thường Gặp (FAQ)

  1. Async/await có làm tăng tốc độ chương trình không?

    • Không trực tiếp, nhưng nó giúp duy trì khả năng phản hồi của ứng dụng trong khi chờ các hoạt động chậm hoàn tất.
  2. Tôi nên sử dụng async/await ở đâu?

    • Sử dụng trong các tác vụ cần chờ đợi như gọi API, đọc tệp, hoặc truy vấn cơ sở dữ liệu.
  3. Có cách nào khác để thực hiện lập trình bất đồng bộ không?

    • Có, bạn có thể sử dụng các phương thức đa luồng truyền thống như Thread hoặc BackgroundWorker, nhưng async/await thường dễ sử dụng hơn.

Bây giờ bạn đã hiểu rõ hơn về asyncawait, hãy bắt đầu áp dụng chúng vào mã C# của bạn!

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào