Bộ điều khiển Async trong ASP.NET MVC: Ưu điểm thực sự / Làm thế nào đạt được?


12

Tôi đã làm việc thông qua một bài viết về các phương pháp điều khiển không đồng bộ trong ASP.NET MVC ( http://visualstudiomagazine.com/articles/2013/07/23/async-ilities-in-aspnet-mvc-4.aspx ) và tôi nghĩ Tôi có thể bị mất điểm.

Hãy xem xét phương pháp này tôi đã viết, rất giống với một ví dụ từ bài viết:

[HttpGet]
[AsyncTimeout(8000)]
[HandleError(ExceptionType = typeof(TimeoutException), View = "TimedOut")]
public async Task<ActionResult> Index(CancellationToken cancellationToken)
{
    WidgetPageViewModel model = new WidgetPageViewModel()
    {
        toAdd = new Widget()
    };
    model.all = await _repo.GetAllAsync(cancellationToken);
    return View(model);
}

Theo tôi hiểu, đây là cách mọi thứ sẽ diễn ra trong thời gian chạy:

  1. Một luồng ASP.NET sẽ được tạo cho một yêu cầu HTTP đến.

  2. Chuỗi này sẽ (có lẽ đã thực hiện một số công việc sơ bộ cần thiết) nhập phương thức Index () của tôi ở trên.

  3. Thực thi sẽ đạt được từ khóa "chờ" và khởi động quy trình thu thập dữ liệu trên một luồng khác.

  4. Chuỗi "ASP.NET" ban đầu sẽ trở về mã được gọi là phương thức xử lý của tôi, với một thể hiện của lớp Nhiệm vụ là giá trị trả về.

  5. Mã cơ sở hạ tầng được gọi là phương thức xử lý của tôi sẽ tiếp tục hoạt động trên luồng "ASP.NET" ban đầu, cho đến khi nó đạt đến điểm cần sử dụng đối tượng ActionResult thực tế (ví dụ để hiển thị trang).

  6. Sau đó, người gọi sẽ truy cập vào đối tượng này bằng cách sử dụng thành viên Task.Result, điều này sẽ khiến nó (tức là luồng "ASP.NET") chờ đợi chuỗi được tạo hoàn toàn trong bước # 3 ở trên.

Tôi không thấy những gì nó đạt được so với cùng một thứ mà không chờ đợi / không đồng bộ, ngoại trừ hai điều tôi cho là không đáng kể:

  • Chuỗi người gọi và luồng công nhân được tạo bởi await có thể hoạt động song song trong một khoảng thời gian (phần "cho đến khi" của số 5 ở trên). Linh cảm của tôi là khoảng thời gian đó là khá nhỏ. Khi cơ sở hạ tầng gọi vào một phương thức của bộ điều khiển, tôi nghĩ rằng nó thường cần ActionResult thực tế của lệnh gọi bộ điều khiển trước khi nó có thể làm được nhiều hơn (nếu có gì).

  • Có một số cơ sở hạ tầng mới hữu ích liên quan đến thời gian chờ và hủy bỏ các hoạt động của bộ điều khiển không đồng bộ chạy dài.

Mục đích của việc thêm các phương thức điều khiển async được cho là để giải phóng các luồng công nhân ASP.NET đó để thực sự trả lời các yêu cầu HTTP. Những chủ đề này là một nguồn tài nguyên hữu hạn. Thật không may, tôi không thấy cách mô hình được đề xuất trong bài viết thực sự phục vụ để bảo tồn các chủ đề này. Và ngay cả khi nó thực hiện, và bằng cách nào đó giảm bớt gánh nặng xử lý yêu cầu đối với một số luồng không -ASP.NET, thì điều đó thực hiện được gì? Các luồng có khả năng xử lý yêu cầu HTTP khác nhiều so với các luồng nói chung không?


Execution will reach the "await" keyword and kick off a data acquisition process on another thread-- Không cần thiết. asynckhông yêu cầu một chủ đề khác ... Đó là một tiếp tục. Nó có thể được thực hiện bằng cách sắp xếp lại các hướng dẫn trên cùng một chủ đề.
Robert Harvey


"Thực thi sẽ đạt được từ khóa đang chờ và khởi động một quy trình thu thập dữ liệu trên một luồng khác." bạn đã nhận được điều này ngược lại: sự chờ đợi là khi nó quay trở lại. Hãy thử và chia nó ra để bạn lưu kết quả từ GetAllAsync () vào một biến và chờ đợi thay vào đó và xem liệu nó có trở nên rõ ràng hơn không.
Esben Skov Pedersen

Câu trả lời:


9

ASP.Net không sử dụng Thư viện song song tác vụ (TPL) bị giới hạn về số lượng yêu cầu, nó có thể xử lý đồng thời bởi số lượng luồng trong nhóm luồng. ASP.Net sử dụng TPL bị giới hạn bởi CPU / bộ nhớ / IO của các yêu cầu xử lý máy.

Thư viện song song tác vụ (TPL) không tiêu thụ các luồng theo cách bạn dường như nghĩ. Nhiệm vụ không phải là chủ đề, chúng là một trình bao bọc xung quanh một số đơn vị tính toán. Bộ lập lịch tác vụ chịu trách nhiệm thực thi từng tác vụ trên bất kỳ luồng nào không bận. Trong thời gian chạy, chờ đợi một tác vụ không chặn luồng, nó chỉ dừng trạng thái thực thi để nó có thể tiến hành sau đó.

Thông thường, một yêu cầu HTTP sẽ được xử lý bởi một luồng duy nhất, loại bỏ hoàn toàn luồng đó khỏi nhóm cho đến khi phản hồi được trả về. Với TPL, bạn không bị ràng buộc bởi ràng buộc này. Bất kỳ yêu cầu nào bắt đầu tiếp tục với mỗi đơn vị tính toán được yêu cầu để tính toán một phản hồi có thể thực hiện trên bất kỳ luồng nào trong nhóm. Với mô hình này, bạn có thể xử lý nhiều yêu cầu đồng thời hơn so với tiêu chuẩn ASP.Net.


Vì vậy, khi chủ đề ASP.NET được trả về hồ bơi? Khi từ khóa "await" được nhấn?
1172763

async / await + TPL cho phép trình biên dịch chia mã của bạn thành các đơn vị tính toán độc lập được thực thi bởi bộ lập lịch tác vụ. Một chủ đề được trả về khái niệm cho nhóm khi bộ lập lịch tác vụ không có nhiều tác vụ có thể được thực thi và luồng hoàn thành công việc được giao cho nó.
chết

Điều này đúng về mặt khái niệm và có lẽ là một câu trả lời hữu ích ... tuy nhiên thực tế chỉ phức tạp hơn một chút do sự linh hoạt của luồng .
John Wu
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.