Tìm hiểu về Async và Await trong Asp.Net

Lập trình bất đồng bộ (Asynchronous Programing) là cách viết code để nhiều phương thức có thể chạy cùng một lúc mà không phải chờ đợi phụ thuộc vào nhau, nó khác với lập trình tuần tự (Synchronous Programing) là phương thức A hoàn thành rồi mới chạy đến phương thức B.

Việc ứng dụng lập trình bất đồng bộ để xử lý các hàm không phụ thuộc vào nhau chạy một cách đồng thời sẽ đem lại hiệu quả đáng kể đối với tốc độ chương trình và trải nghiệm người dùng, kể từ .Net 4.5  việc lập trình bất đồng bộ sẽ đơn giản hơn trước với sự hỗ trợ của cặp từ khóa Async & Await.

 

Lợi ích của Asynchronous Programing

Có 2 vấn đề rất quan trọng được đặt ra với mọi phần mềm đó là tính hữu dụng (Usability) và hiệu suất (Performance) của phần mềm. 

Ví dụ giả sử khi người dùng click vào button Save, sẽ có một số công việc phải thực hiện trong chương trình ta cần làm như là:  Xử lý tính toán dữ liệu, đẩy dữ liệu sau khi tính toán sang 1 api service khác, lưu kết quả trả về và log xuống database hệ thống... với một ứng dụng viết theo kiểu thông thường ta sẽ phải xử lý từng bước một, xong việc này tiếp tục thực hiện việc kia, lúc đó trên màn hình giao diện người dùng ứng dụng sẽ ở dạng đang xử lý và việc phải chờ đợi khiến người dùng nhiều khi thực sự mệt mỏi.

Đây chính là lý do ngày nay có rất nhiều ứng dụng áp dụng việc lập trình Asynchronous để cải thiện vấn đề này, với cách lập trình mới, các công việc cần xử lý như mình nói ở trên có thể tách ra để xử lý một cách đồng thời, do đó phần mềm vấn đáp ứng được yêu cầu bài toán (Usability) và sẽ bớt đi thời gian chờ đợi đối với người sử dụng (Performance)

Về lý thuyết cái này thực sự mình đọc khá nhiều bài nhưng không biết viết thế nào diễn đạt được hết ý của nó :), ở đây mình chủ yếu tập trung vào làm ví dụ mà qua đó các bạn có thể sẽ dễ hính dung hơn.

Các bạn có thể đọc thêm về Asynchronous Programing ở một số link dưới đây:

https://docs.microsoft.com/en-us/dotnet/csharp/async

https://msdn.microsoft.com/library/hh191443(vs.110).aspx

Để làm ví dụ này mình tạo một project có tên AynchronousProgramming với Asp.Net MVC5

Trong class ContentManager mình thêm 2 hàm GetContent() & GetNumber(), sử dụng Thread.Sleep() để giả định hàm đó chạy sẽ rất chậm :)

public class ContentManagement
    {
        //synchronous method
        public string GetContent()
        {
            Thread.Sleep(5000);
            return "content";
        }

        public int GetNumber()
        {
            Thread.Sleep(3000);
            return 3;
        }
       
    }

Hàm GetContent() sẽ xử lý mất một khoảng thời gian là 5 seconds, hàm GetNumber() sẽ mất 3 seconds. Với cách lập trình tuần tự (synchronous programming), trong Index() method của DefaultController ta sẽ viết như sau.

public ActionResult Index()
        {
            Stopwatch watch = new Stopwatch();
            watch.Start();
            ContentManagement service = new ContentManagement();
            service.GetContent();
            service.GetNumber();
            watch.Stop();
            ViewBag.Milliseconds = watch.ElapsedMilliseconds;
            return View();
        }

Ngoài Index.cshtml ta hiện giá trị từ ViewBag trả về

<h2>Elapsed Time: @ViewBag.Milliseconds</h2>

Ta chạy ứng dụng, các bạn sẽ thấy thời gian xử lý trả về để thực hiện cả 2 phương thức sẽ là 5+3 = 8 giây.

Nói ngoài lề một chút, Stopwatch là một class rất hưu ích hỗ trợ chúng ta trong việc tính thời gian thực thi hàm.

Rõ ràng như ở trên, hàm GetContent() sẽ phải thực thi xong, sau đó mới tiếp tục xử lý đến hàm GetNumber(), việc này dẫn đến chương trình sẽ bị chậm trễ. 

 

Chúng ta có thể cải thiện bằng cách thực thi 2 hàm này song song cùng một lúc, Class ContentManagement sẽ chỉnh lại một chút như sau

public class ContentManagement
    {

        //asynchronous method
        public async Task<string> GetContentAsync()
        {
            await Task.Delay(5000);
            return "content async";
        }

        public async Task<int> GetNumbreAsync()
        {
            await Task.Delay(3000);
            return 3;
        }
    }

Phía ngoài DefaultController ta sẽ gọi 2 phương thức bất đồng bộ trên như sau.

public async Task<ActionResult> IndexAsync()
        {
            Stopwatch watch = new Stopwatch();
            watch.Start();
            ContentManagement service = new ContentManagement();
            var contentTask = service.GetContentAsync();
            var numberTask = service.GetNumbreAsync();
            await contentTask;
            await numberTask;
            watch.Stop();
            ViewBag.Milliseconds = watch.ElapsedMilliseconds;
            return View();
        }

Phía ngoài IndexAsync.cshtml ta hiện thị giá trị trả về từ ViewBag

<h2>Elapsed Time: @ViewBag.Milliseconds</h2>

Ta chạy ứng dụng, và các bạn sẽ thấy thời gian thực thi sẽ chỉ là 5 giây, do 2 phương thức đã chạy cùng một thời điểm mà không phải đợi lẫn nhau. Các bạn có thể thấy ngay được sự lợi hại của Async & Await trong trường hợp này :).

 

Sự khác nhau giữa Asynchronous Programing và Multi-Threading

Khi tìm hiểu về Asynchronous Programing mình cũng có một chút băn khoăn vê sự khác nhau giữa 2 thằng này. Sau khi lòng vòng trên mạng mình đọc được bài này rất hay và chi tiết.

Concurrency vs Multi-threading vs Asynchronous Programming : Explained

Tóm tắt một số ý chính theo mình hiểu có một số điểm khác nhau cơ bản như sau (Các bạn có thể tìm hiểu kỹ hơn ở link trên nhé )

- Với Multi-Threading thì mỗi task sẽ chạy trên 1 thread, và do vậy khi có nhiều task chạy đồng thời việc tăng thêm thread sẽ có hạn chế bởi vấn đề về phần cứng

- Với Asynchronous Programing thì một task có thể khởi tạo ở thread này và hoàn thành ở thread kia, mỗi thread có thể chạy nhiều task cùng một lúc cũng như một task có thể chạy trên nhiều thread. Với kiến trúc này sẽ linh động hơn và sẽ bớt sự phụ thuộc vào tài nguyên phần cứng hệ thống.

 

Ví dụ trên của mình không bao quát được hết các vấn đề, nhưng cũng có thể giúp các bạn có được một cái nhìn cơ bản về Asynchronous Programing.

Nắm được bản chất và cách sử dụng và áp dụng lập trình bất đồng bộ với từ khóa Async & Await sẽ mang lại hiệu quả rõ rệt trong ứng dụng mà các bạn phát triển.

Các bạn có thể download ví dụ đầy đủ của bài viết dưới đây

 

Download Source

Related Post


Tìm hiểu về Ajax Helpers trong Asp.Net MVC
Friday, July 28, 2017
Bên cạnh việc sử dụng Ajax với jQuery thì Asp.Net MVC còn có Ajax Helper method hỗ trợ rất tốt cho lập trình viên .Net xây dựng các chức năng xử lý bất đồng bộ (asynchronously) một cách dễ dàng và nhanh chóng. Trong bài này mình sẽ làm một số ví dụ nhỏ về cách sử dụng Ajax Helpers trong Asp.Net MVC5
Export Excel cực dễ với ClosedXML
Friday, July 21, 2017
ClosedXML là một thư viện hỗ trợ lập trình viên .Net tạo ra các file Excel 2007+ để làm report báo cáo một cách dễ dàng và nhanh chóng, ClosedXML giúp lập trình viên làm việc với excel theo các tiếp cận hướng đối tượng mà không cần phải quan tâm quá nhiều đến cấu trúc quá phức tạp của XML.
Search

Đăng ký nhận bài mới


Category

Blog Archive