2014-10-10 47 views
6

Nghĩ rằng tôi đã được xử lý trên ConfigureAwait, sau đó tôi đã thử nghiệm.C# Task ConfigureAwait

Sự hiểu biết của tôi là ConfigureAwait(false) sẽ chỉ tạo sự khác biệt nếu có ngữ cảnh đồng bộ hóa.

ASP, WPF, v.v. phải có ngữ cảnh, nhưng không nên sử dụng ứng dụng điều khiển và ứng dụng dịch vụ.

Để xem cách nó hoạt động tôi đã thực hiện một ứng dụng Web API và bao gồm các phương pháp sau đây:

// GET api/values/5 
public async Task<string> Get (int id) 
{ 
    var syncCtx = SynchronizationContext.Current; 

    int startThreadId = Thread.CurrentThread.ManagedThreadId; 

    await Task.Delay(TimeSpan.FromSeconds(3)).ConfigureAwait(true); 

    int endThreadId = Thread.CurrentThread.ManagedThreadId; 

    return "Start Thread ID: " + startThreadId.ToString() + 
      ": End Thread ID: " + endThreadId.ToString(); 
} 

dự đoán của tôi là không có ConfigureAwait hoặc ConfigureAwait thiết lập để true, tôi sẽ thấy cùng một ID chủ đề trước và sau khi chờ đợi.

Một vài thử nghiệm đầu tiên của tôi cho thấy chính xác điều đó với bộ đúng như trên.

Chạy sau mã bắt đầu và kết thúc trên các id chuỗi khác nhau bất kể ConfigureAwait.

Tôi đã thêm syncCtx để thuyết phục bản thân mình Tôi có ngữ cảnh.

Thông báo trước tôi đã đọc là nếu tác vụ đã hoàn tất, bạn sẽ không được bảo đảm cùng một ID. Đó có phải là trường hợp ở đây không? Nếu vậy, tại sao là trường hợp?

Tôi đã thiết lập thử nghiệm ngây thơ hoặc thiếu sót chưa? Nếu vậy, thử nghiệm thích hợp là gì?

Tôi bắt đầu xuống đường dẫn này trong ứng dụng giao diện điều khiển/dịch vụ và nhận ra rằng tôi không nhận được cùng một ID luồng. Tôi đã thêm ConfigureAwait(false) như được đề xuất trong hầu hết các bài viết "thực hành tốt nhất" mà tôi đã xem. Vì tôi thích xem mọi thứ thực sự hoạt động như thế nào, tôi đã thử kiểm tra ID chủ đề. Nhìn thấy chúng khác nhau đã dẫn tôi qua một số tìm kiếm dẫn đến mã trên.

Trả lời

8

Làm ConfigureAwait(true) (hoặc chỉ để nguyên khỏi giá trị mặc định) không làm cho nó chạy trên cùng một chuỗi. Nó cho biết SynchronizationContext.Current để làm một Post hoặc Send với phần còn lại của tính liên tục. Cách Post hoặc Send thực sự chạy mã đó không được định nghĩa.

WindowsFormsSynchronizationContextDispatcherSynchronizationContext (ngữ cảnh của WinForms và WPF) cả hai sẽ đặt tiếp tục vào hàng đợi thư được xử lý bởi Máy bơm thư (chuỗi giao diện người dùng).

Mặt khác, AspNetSynchronizationContext (đó là những gì bạn đang chạy dưới) chỉ cần đặt một số thông tin trạng thái (như thiết lập HttpContext.Current về giá trị cũ), sau đó xếp hàng công việc trên chuỗi chủ đề có sẵn tiếp theo. Không có "Message Pump" cho ASP.NET, nó chỉ làm tất cả công việc của nó trên nhóm thread, do đó, không có điểm trong cố gắng để có được cùng một chủ đề ra khỏi hồ bơi thread tại một thời gian sau đó, chủ đề đó có thể đã bị phá hủy khi thời gian tiếp tục diễn ra.

Lần bạn nhìn thấy cùng một ID trước và sau khi bạn vừa mới may mắn và cùng một luồng đã được kéo ra khỏi nhóm luồng trước và sau khi tiếp tục.

Tôi khuyên bạn nên đọc bài viết trên tạp chí MSDN "It's All About the SynchronizationContext", nó đi vào chi tiết giải thích cách SynchronizationContext hoạt động và đi vào chi tiết một chút về 4 loại ngữ cảnh được tích hợp trong .NET.

+0

Chỉ cần làm rõ tôi không * cố gắng * để có được cùng một chuỗi, chỉ cần cố gắng khắc phục sự hiểu lầm của tôi về hành vi của ConfigureAwait. – jeffa00

+0

Thats tốt, tôi vẫn sẽ đọc bài báo tạp chí MSDN. Nó bao gồm các chủ đề này khá tốt. –

+0

Tôi chắc chắn có kế hoạch đọc bài viết đó. Cảm ơn các liên kết. – jeffa00

6

SynchronizationContext! = Thread. Nếu bạn đang sử dụng một cái gì đó giống như WPF với thời gian hoạt động Dispatcher của nó thì, có, của nóSynchronizationContext xảy ra được gắn với một chuỗi cụ thể. Tuy nhiên những thứ như ASP.NET và WCF không phải là chủ đề affine, họ chỉ mang theo cùng với họ bối cảnh môi trường cụ thể mà cần phải được phục hồi trên bất cứ chủ đề họ bắt đầu thực hiện tiếp theo. Chúng có thể ảnh hưởng đến một chủ đề cụ thể pool, nhưng, một lần nữa, không phải là một chuỗi cụ thể.

Đây chính là lý do tại sao giới thiệu SynchronizationContext trừu tượng: nó cho phép các khung công tác khác nhau quyết định chính xác mối quan hệ nào với chúng và cho phép cơ sở hạ tầng không đồng bộ/chờ đợi hoạt động tốt nhất theo cách hoàn toàn bất khả tri.

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