Lập trình bất đồng bộ trong C# – Async & Await

Bài viết này giới thiệu với các bạn cách làm việc với async và await trong C# để triển khai lập trình bất đồng bộ.

Trước đây chúng ta ta thường xử lý các tiến trình theo một cách đồng bộ. Giả sử một chuỗi các công việc được thực hiện một cách tuần tự theo thứ tự A, B, C, D. Công việc A thực hiện trước công việc B, công việc B thực hiện trước công việc C… Do vậy, công việc D muốn được thực thi đều phải chờ các tiến trình A, B, C xử lý hoàn tất. Một chuỗi tiến trình như vậy có thể bị ngắt quãng nếu như một công việc nào đó chưa thực thi xong hay rơi vào trạng thái not responding, các công việc sau nó chắc chắn sẽ không được thực thi. Thực tế như một dây chuyền sản xuất trong một khu nhà máy được xem là đồng bộ.

Trên nền .NET FrameWork 4.5, lập trình C# với async. Một công việc B có thể được thực thi trước công việc A, cho dù công việc A chưa hoàn thành.

Một số các thành phần dưới đây khi thao tác với chúng theo cách không đồng bộ sẽ đem lại hiệu quả cao:

Web access: HttpClient, SyndicationClient.

Working with files: StorageFile, StreamWriter, StreamReader, XmlReader.

Working with images: MediaCapture, BitmapEncoder, BitmapDecoder.

WCF programming: Synchronous and Asynchronous Operations.

Working with sockets: Socket.

Async and await: Tại phần này chúng ta sẽ tìm hiểu và làm rõ tại sao một phương thức async lại không chặn (blocking) một method. Một async method có thể trả về kiểu Void hoặc Task.

Task: Một Task không trả về dữ liệu (nó là kiểu void). Một Task<int> trả về một thành phần kiểu int. Đây là một kiểu chung chung.

Chú ý: Một async method sẽ chạy theo kiểu đồng bộ (synchronously) nếu nó không có từ khóa await.

Chương trình: Sử dụng từ khóa asyncawait để chạy một phương thức bất đồng bộ. Trong chương trình chúng ta sẽ có một method HandleFileAsync, chương trình này sẽ thực hiện đọc các dòng dữ liệu trong một file text.

First:

Chúng ta sẽ tạo một Task với method ProcessDataAsync như là một đối số. Chúng ta sẽ bắt đầu task và đợi cho đến khi nó kết thúc.

Messages:

Method này sẽ hiển thị trạng thái trước khi bắt đầu. Khi nó kết thúc nó sẽ hiển thị kết quả.

ProcessDataAsync:

Trong ProcessDataAsync, chúng ta sẽ gọi method HandleFileAsync. Tại đây mình sẽ hiển thị trạng thái message ra màn hình.

HandleFileAsync:

Trong HandleFileAsync chúng ta sử dụng kiểu StreamReadermethod ReadToEndAsync. Đồng thời sau đó chúng ta sẽ thực hiện một vài tính toán.

using System;

using System.IO;

using System.Threading.Tasks;

class Program

{

    static void Main()

    {

    // Create task and start it.

    // ... Wait for it to complete.

    Task task = new Task(ProcessDataAsync);

    task.Start();

    task.Wait();

    Console.ReadLine();

    }

    static async void ProcessDataAsync()

    {

    // Start the HandleFile method.

    Task<int> task = HandleFileAsync("C:\\enable1.txt");

    // Control returns here before HandleFileAsync returns.

    // ... Prompt the user.

    Console.WriteLine("Please wait patiently " +

        "while I do something important.");

    // Wait for the HandleFile task to complete.

    // ... Display its results.

    int x = await task;

    Console.WriteLine("Count: " + x);

    }

    static async Task<int> HandleFileAsync(string file)

    {

    Console.WriteLine("HandleFile enter");

    int count = 0;

    // Read in the specified file.

    // ... Use async StreamReader method.

    using (StreamReader reader = new StreamReader(file))

    {

        string v = await reader.ReadToEndAsync();

        // ... Process the file data somehow.

        count += v.Length;

        // ... A slow-running computation.

        //     Dummy code.

        for (int i = 0; i < 10000; i++)

        {

        int x = v.GetHashCode();

        if (x == 0)

        {

            count--;

        }

        }

    }

    Console.WriteLine("HandleFile exit");

    return count;

    }

}

Output: initial

HandleFile enter

Please wait patiently while I do something important.

Output: final

HandleFile enter

Please wait patiently while I do something important.

HandleFile exit

Count: 1916146

Cảm ơn các bạn đã theo dõi và hẹn gặp lại ở các bài tiếp theo.

Tags: