2013-08-22 40 views
69

Tôi có đoạn code WebAPI kiểm tra sau, tôi không sử dụng WebAPI trong sản xuất nhưng tôi làm điều này vì một cuộc thảo luận tôi đã về câu hỏi này: WebAPI Async questionTại sao HttpContext.Current null sau khi đang chờ?

Anyways, đây là phương pháp vi phạm WebAPI:

public async Task<string> Get(int id) 
{ 
    var x = HttpContext.Current; 
    if (x == null) 
    { 
     // not thrown 
     throw new ArgumentException("HttpContext.Current is null"); 
    } 

    await Task.Run(() => { Task.Delay(500); id = 3; }); 

    x = HttpContext.Current; 
    if (x == null) 
    { 
     // thrown 
     throw new ArgumentException("HttpContext.Current is null"); 
    } 

    return "value"; 
} 

Tôi đã tin rằng ngoại lệ thứ hai được mong đợi bởi vì khi hoàn tất, nó có thể sẽ nằm trên một luồng khác, trong đó HttpContext.Current làm biến chủ đề sẽ không còn giải quyết cho giá trị thích hợp nữa. Bây giờ, dựa trên bối cảnh đồng bộ hóa, nó thực sự có thể bị buộc quay trở lại cùng một luồng sau khi chờ đợi nhưng tôi không làm bất cứ điều gì lạ mắt trong thử nghiệm của mình. Đây chỉ là cách sử dụng đơn giản, ngây thơ của await.

Trong nhận xét trong câu hỏi khác, tôi được thông báo rằng HttpContext.Current sẽ giải quyết sau một thời gian chờ đợi. Thậm chí còn có một bình luận khác về câu hỏi này cho thấy tương tự. Vì vậy, những gì là sự thật? Nó có nên giải quyết không? Tôi nghĩ không, nhưng tôi muốn có một câu trả lời có thẩm quyền về điều này bởi vì asyncawait là đủ mới mà tôi không thể tìm thấy bất kỳ điều gì dứt khoát.

TL; DR: Có phải HttpContext.Current có khả năng null sau await?

+2

Câu hỏi của bạn không rõ ràng - bạn đã nói những gì bạn mong đợi sẽ xảy ra và nhận xét cho biết rằng * là * điều gì đang xảy ra ... vậy điều gì khiến bạn khó hiểu? –

+0

@ user2674389, điều này gây hiểu nhầm. Đó là 'AspNetSynchronizationContext' sẽ xử lý' HttpContext', không phải 'đang chờ '. Hơn nữa, việc gọi lại liên tục cho 'await' có thể (và rất có thể sẽ xảy ra) trên một luồng khác cho mô hình thực thi API Web. – Noseratio

+0

được chỉnh sửa để đặt câu hỏi ngắn gọn – welegan

Trả lời

110

Hãy đảm bảo bạn đang viết ứng dụng ASP.NET 4.5 và nhắm mục tiêu 4.5. asyncawait có hành vi không xác định trên ASP.NET trừ khi bạn đang chạy trên 4.5 đang sử dụng ngữ cảnh đồng bộ hóa "tác vụ thân thiện" mới.

Đặc biệt, điều này có nghĩa bạn phải:

  • Đặt httpRuntime.targetFramework-4.5, hoặc
  • Trong appSettings của bạn, thiết lập aspnet:UseTaskFriendlySynchronizationContext để true.

Thông tin khác là available here.

+0

Tôi chắc chắn trên .NET 4.5 – welegan

+2

Tôi vừa tạo một dự án ASP.NET 4.5 WebAPI mới, sao chép/dán mã của bạn và thực hiện một thử nghiệm. Nó làm việc hoàn hảo cho tôi (không phải ngoại lệ được ném). Vui lòng kiểm tra lại xem bạn có đang chạy trên * và nhắm mục tiêu * 4.5 không. –

+2

Tôi có khung mục tiêu: Khuôn khổ .NET 4.5. Tôi không biết phải nói gì với bạn, nó chắc chắn là không có trên máy địa phương của tôi. – welegan

2

là thử nghiệm của tôi thiếu sót, hoặc là có một số yếu tố web.config tôi là thiếu đây mà có thể làm HttpContext.Current giải quyết một cách chính xác sau một chờ đợi?

Thử nghiệm của bạn không hoàn thiện và HttpContext.Current không được rỗng sau khi chờ đợi vì trong ASP.NET Web API khi bạn chờ đợi, điều này sẽ đảm bảo rằng mã đang chờ đợi này được chuyển đúng HttpContext có mặt trước khi chờ đợi.

+0

Bạn có chắc chắn về cùng một chuỗi tiếp tục cho WebAPI không? Tôi xử lý [trường hợp] (http://stackoverflow.com/q/18284998/1768303) ở đâu đó là một chủ đề khác. – Noseratio

+4

ASP.NET sẽ tiếp tục trên bất kỳ chuỗi chủ đề nào của luồng, nhưng với ngữ cảnh yêu cầu chính xác. –

+2

Có, bạn là đúng, các chủ đề có thể không giống nhau nhưng HttpContext.Current sẽ giống như trước khi chờ đợi. Tôi đã cập nhật câu hỏi của mình. –

16

Như @StephenCleary một cách chính xác chỉ ra, bạn cần điều này trong web.config của bạn:

<httpRuntime targetFramework="4.5" /> 

Khi tôi lần đầu tiên được xử lý sự cố này, tôi đã làm một tìm kiếm giải pháp toàn cho ở trên, khẳng định nó đã có mặt tại tất cả các dự án web của tôi và nhanh chóng loại bỏ nó như là thủ phạm. Cuối cùng, tôi thấy các kết quả tìm kiếm đó trong ngữ cảnh đầy đủ:

<!-- 
    For a description of web.config changes for .NET 4.5 see http://go.microsoft.com/fwlink/?LinkId=235367. 

    The following attributes can be set on the <httpRuntime> tag. 
    <system.Web> 
     <httpRuntime targetFramework="4.5" /> 
    </system.Web> 
--> 

Doh.

Bài học: Nếu bạn nâng cấp dự án web lên 4.5, bạn vẫn cần phải thiết lập cài đặt đó theo cách thủ công.

+14

Một thứ khác nữa là khác với Andrew

+0

cảm ơn bạn. @Andrew – Barry

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