2015-05-22 14 views
9

Tôi biết đó là một câu hỏi phổ biến, nhưng tôi đã đọc một loạt các bài báo và cảm thấy bối rối. Và bây giờ tôi nghĩ rằng nó sẽ là tốt hơn không để đọc chúng ở tất cả)).ASP.NET và async - cách hoạt động?

Vì vậy, làm thế nào ASP.NET làm việc (chỉ khoảng đề):

  1. yêu cầu http được phục vụ bởi thread từ bể thread.
  2. trong khi yêu cầu đang xử lý chuỗi này đang bận, vì yêu cầu đang xử lý bên trong chính xác luồng này.
  3. khi yêu cầu xử lý hoàn tất, luồng trả về nhóm luồng, máy chủ gửi phản hồi.

Hành vi được mô tả này có đúng không?

Điều gì thực sự xảy ra khi tôi bắt đầu nhiệm vụ mới bên trong bộ điều khiển ASP.NET MVC?

public ActionResult Index() 
{ 
    var task1 = Task.Factory.StartNew(() => DoSomeHeavyWork()); 
    return View(); 
} 

private static async Task DoSomeHeavyWork() 
{ 
    await Task.Delay(5000); 
} 
  1. điều khiển hành động bắt đầu thực hiện trong chủ đề đó sẽ xử lý yêu cầu hiện tại - T1.
  2. nhóm luồng phân bổ một luồng khác (T2) cho nhiệm vụ 1.
  3. task1 bắt đầu "ngay lập tức" bên trong T2.
  4. Kết quả xem trả về "ngay lập tức".
  5. ASP.NET thực hiện một số công việc, máy chủ gửi phản hồi, T1 trở về nhóm chủ đề, T2 vẫn còn hoạt động.
  6. sau một thời gian khi DoSomeHeavyWork sẽ kết thúc, chuỗi T2 sẽ được trả về nhóm chủ đề.

Có đúng không?

Bây giờ cho phép nhìn vào hành động async

public async Task<ActionResult> Index() 
{ 
    await DoSomeHeavyWork(); 
    return View(); 
} 

, tôi hiểu sự khác biệt với mẫu mã trước đó, nhưng không phải là quá trình này, trong ví dụ này hành vi này là như sau:

  1. hành động bắt đầu thực thi bên trong luồng xử lý yêu cầu hiện tại - T1.
  2. DoSomeHeavyWork "ngay lập tức" trả về một tác vụ, hãy gọi nó là "task1".
  3. T1 trở về nhóm chủ đề.
  4. sau khi kết thúc DoSomeHeavyWork, hành động Index tiếp tục thực thi.
  5. sau khi thực thi hành động chỉ mục, máy chủ sẽ gửi phản hồi.

Xin giải thích những gì xảy ra giữa các điểm 2 và 5, các câu hỏi là:

  1. là DoSomeHeavyWork xử lý bên trong task1 hoặc nơi (nơi nó được "chờ đợi")? Tôi nghĩ đây là một câu hỏi quan trọng.
  2. chuỗi nào sẽ tiếp tục xử lý yêu cầu sau khi đang chờ - bất kỳ chủ đề nào mới từ nhóm chủ đề, phải không?
  3. yêu cầu tạo chuỗi phân bổ từ nhóm chủ đề, nhưng phản hồi sẽ không được gửi cho đến khi DoSomeHeavyWorkAsync kết thúc và không thành vấn đề trong đó chuỗi này thực thi. Nói cách khác, theo đơn yêu cầuduy nhất nhiệm vụ cụ thể (DoSomeHeavyWork) không có lợi ích khi sử dụng async. Nó có đúng không ?
  4. nếu tuyên bố trước là chính xác, thì tôi không hiểu cách async có thể cải thiện hiệu suất cho nhiều yêu cầu với cùng một nhiệm vụ đơn. Tôi sẽ cố gắng giải thích. Giả sử rằng thread thread có 50 luồng có sẵn để xử lý các yêu cầu. Yêu cầu duy nhất phải được xử lý ít nhất bởi một chuỗi duy nhất từ ​​nhóm chủ đề, nếu yêu cầu bắt đầu một luồng khác, thì tất cả chúng sẽ được lấy từ nhóm luồng, ví dụ: yêu cầu có một luồng để xử lý, bắt đầu 5 nhiệm vụ khác nhau song song chờ tất cả chúng, thread thread sẽ có 50 - 1 - 5 = 44 thread miễn phí để xử lý các yêu cầu gửi đến - vì vậy đây là một song song, chúng ta có thể cải thiện hiệu suất cho single yêu cầu, nhưng chúng tôi giảm số lượng yêu cầu có thể được xử lý. Vì vậy, theo yêu cầu chế biến trong ASP.NET tôi giả sử rằng chỉ có nhiệm vụ mà bằng cách nào đó bắt đầu IO hoàn thành chủ đề có thể đạt được một mục tiêu của async (TAP). Nhưng làm thế nào IO hoàn thành thread gọi lại thread thread thread trong trường hợp này?
+0

'đang chờ đợi 'Một số câu trả lời có giá trị cho câu hỏi này. – Xmindz

Trả lời

5

Đây có phải là hành vi được mô tả đúng không?

Có.

Có đúng không?

Có.

là DoSomeHeavyWork được xử lý bên trong task1 hoặc ở đâu (trong đó "đang chờ")? Tôi nghĩ đây là một câu hỏi quan trọng.

Từ mã hiện tại, DoSomeHeavyWork sẽ đợi không đồng bộ Task.Delay để hoàn tất. Có, điều này sẽ xảy ra trên cùng một luồng được phân bổ bởi thread-pool, nó sẽ không quay bất kỳ chủ đề mới nào. Tuy nhiên, không có gì đảm bảo rằng nó sẽ là cùng một chủ đề.

chuỗi nào sẽ tiếp tục xử lý yêu cầu sau khi đang chờ?

Vì chúng ta đang nói về ASP.NET, đó sẽ là một chuỗi chủ đề tùy ý, với HttpContext được sắp xếp trên nó. Nếu đây là ứng dụng WinForms hoặc WPF, bạn sẽ nhấn lại chuỗi giao diện người dùng ngay sau await, với điều kiện bạn không sử dụng ConfigureAwait(false).

yêu cầu sản xuất chủ đề phân bổ từ bể thread, nhưng phản ứng của sẽ không được gửi cho đến khi DoSomeHeavyWorkAsync kết thúc và nó không quan trọng, trong đó chủ đề phương pháp này thực hiện. Nói cách khác, theo yêu cầu duy nhất và nhiệm vụ cụ thể đơn lẻ (DoSomeHeavyWork) không có lợi ích gì khi sử dụng async. Nó có đúng không ?

Trong trường hợp cụ thể này, bạn sẽ không thấy lợi ích của việc không đồng bộ.async tỏa sáng khi bạn có yêu cầu đồng thời nhấn máy chủ, và rất nhiều trong số họ đang làm IO ràng buộc công việc. Khi sử dụng async trong khi nhấn cơ sở dữ liệu, ví dụ, bạn có thể giải phóng luồng thread-pool cho khoảng thời gian truy vấn thực hiện, cho phép cùng một luồng xử lý nhiều yêu cầu hơn trong khi đó.

Nhưng cách trình hoàn thành IO gọi lại chuỗi chủ đề luồng trong trường hợp này?

Bạn phải tách song song và đồng thời. Nếu bạn cần tính toán sức mạnh để làm công việc CPU bị ràng buộc song song, async không phải là công cụ sẽ làm cho nó xảy ra. Mặt khác, nếu bạn có nhiều hoạt động ràng buộc đồng thời IO, như nhấn cơ sở dữ liệu cho hoạt động CRUD, bạn có thể hưởng lợi từ việc sử dụng async bằng cách giải phóng luồng trong khi thao tác IO đang thực hiện. Đó là điểm chính quan trọng cho async.

Nhóm chủ đề có nhóm chuyên đề hoàn thành IO cũng như chuỗi công việc mà bạn có thể xem bằng cách gọi ThreadPool.GetAvailableThreads. Khi bạn sử dụng các hoạt động liên kết IO, luồng truy xuất các cuộc gọi lại là thường là một chuỗi hoàn thành IO và không phải là một chuỗi công nhân. Cả hai đều có hồ bơi khác nhau.

+0

Cảm ơn, rõ ràng. Một câu hỏi nữa - nếu tôi sử dụng thư viện của bên thứ ba và nó có phương pháp được gọi là ví dụ: SomeMethodAsync đó là awaitable sau đó tôi nên quấn nó với await từ khóa hoặc trực tiếp gọi SomeMethodAsync (...). Trong thực tế, tôi không biết liệu nó có sử dụng bất kỳ hoạt động IO nào hay không. – SamousPrime

+2

@SamousPrime Bạn [không nên chặn mã async] (http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html), nó có thể dẫn bạn đến tất cả các loại vấn đề , bao gồm cả deadlocks. Sử dụng 'await'. Nếu bạn không chắc chắn mã đang làm gì, bạn luôn có thể xem nó bằng trình giải mã .NET. –

+0

Ví dụ hữu ích về deadlocks. Nhưng liệu "async" có nghĩa là từ khóa không đồng bộ chính xác hay nó là ý nghĩa chung của không đồng bộ? Tôi yêu cầu vì mẫu sau đây không có bế tắc 'Chỉ mục ActionResult công cộng() { int t = Công việc(). Chế độ xem trả lại ("Chỉ mục"); } tĩnh riêng Nhiệm vụ Công việc() { trả lại Tác vụ.Run (() => Task.Delay (2000) .ContinueWith (t => 1)); } '... – SamousPrime

Các vấn đề liên quan