6

Ai đó có thể chỉ cho tôi một tài nguyên có thể giúp giải thích cách api web (cụ thể sử dụng Owin Self Host) xử lý yêu cầu hủy bỏ?OWIN SelfHost Web Api - Yêu cầu hủy - Làm thế nào nó được thực hiện? Hủy bỏ chủ đề?

Đây là chuỗi các sự kiện tôi đang quan sát:

  • ai đó làm cho một GET từ chrome khiển
  • Api (thông qua một số lớp) tắt đám cháy một truy vấn async SQL
  • một ai đó truy cập vào nút X trong chrome (tôi không biết chính xác điều gì xảy ra trên ổ cắm cho điều này)

Điều gì xảy ra tiếp theo trong Web Api ??

Có một số mã đang chạy trong bộ điều khiển, chuỗi chạy có bị hủy bỏ không? Nếu nó là một bộ điều khiển async đang chờ một Task khác, thì nhiệm vụ đó vẫn còn có một awaiter trong trường hợp nó trả về với một ngoại lệ?

Đối với ngữ cảnh: Tôi có bộ điều khiển async đang chờ Nhiệm vụ (đây là trang web gọi duy nhất) có vẻ như đang ném một ngoại lệ không được giám sát trong một số trường hợp cạnh. Tôi chưa thể cách ly hoặc tái sản xuất được :)

Tôi đã tìm thấy một cái gì đó gọi là HttpResponse.ClientDisconnectedToken, nhưng không biết rõ được hỗ trợ trong Owin Selfhost + là ngay cả điều tốt để sử dụng cho tất cả người dùng hủy .

+0

Chúng tôi không thể giúp bạn trừ khi bạn bị mất mã. Điều này có vẻ như ai đó đang bắn ra một nhiệm vụ mà đi không quan sát, như ngoại lệ nói. Tôi giả định đây là .NET 4.0 –

+0

@YuvalItzchakov: Xin lỗi nếu phần ngoại lệ gây nhầm lẫn (chỉnh sửa để xóa nó). Tôi đã đặt nó như là bối cảnh cho lý do tại sao tôi muốn hiểu những gì api web đang làm với các yêu cầu, câu hỏi thực sự của tôi vẫn còn xung quanh những gì api làm gì? – Vivek

+0

là một cách khác để hỏi cùng một câu hỏi mà bạn đã hỏi trước đó: http://stackoverflow.com/questions/30109260/owen-selfhost-webapi-client-closing-the-connection-during-response-raises-an-e ? – Claies

Trả lời

0

Như bạn nói rằng điều khiển async của bạn đang chờ một Task, mà đôi khi có một số ngoại lệ, tôi đề nghị bạn ContinueWith phương pháp mở rộng cho một nhiệm vụ, mà có thể chạy chỉ khi đó nhiệm vụ của bạn là đứt gãy, như thế này:

task.ContinueWith(
     t => 
     logger.Error(t.Exception.Message, t.Exception); 
     , TaskContinuationOptions.OnlyOnFaulted); 

Đây là cơ chế mặc định để xử lý các ngoại lệ và điều này sẽ hoạt động trong ứng dụng OWIN.

Thứ hai, về việc hủy: nhiệm vụ có thể được bắt đầu với cấu trúc CancellationToken, có thể được sử dụng để hủy tác vụ trong khi thực thi. You can read more in the MSDN article.

HttpResponse.ClientDisconnectedToken được sử dụng cho một tình huống khi khách hàng đã bị ngắt kết nối và yêu cầu không được tiếp tục thực hiện.

Bạn có thể sử dụng thẻ này, hoặc tạo của riêng bạn với CancellationTokenSource, như thế này:

var source = new CancellationTokenSource(); 
var token = source.Token; 

var task = Task.Factory.StartNew(() => 
{ 

    // Were we already canceled? 
    ct.ThrowIfCancellationRequested(); 

    var moreToDo = true; 
    while (moreToDo) 
    { 
     // Poll on this property if you have to do 
     // other cleanup before throwing. 
     if (ct.IsCancellationRequested) 
     { 
      // Clean up here, then... 
      ct.ThrowIfCancellationRequested(); 
     } 

    } 
}, token); 
+0

Cảm ơn bạn đã hiển thị việc sử dụng trên mã thông báo đó, nhưng đó là cách xuống dòng. Tôi chưa từng xác nhận điều gì đang diễn ra: ( – Vivek

+0

Hãy thử thêm xử lý ngoại lệ – VMAtm

+0

> HttpResponse.ClientDisconnectedToken được sử dụng cho một tình huống khi máy khách bị ngắt kết nối và yêu cầu không được tiến hành trong thực thi. ... Nhưng cách tiếp cận mã thông báo này? 'HttpContext.Current == null' cho OWIN tự lưu trữ ứng dụng ... – greatvovan

2

Tôi đã giải quyết điều này bằng cách trao System.OperationCanceledException trong một middleware tùy chỉnh Tôi đã đăng ký trước khi WebApi.

public class ExceptionHanldingMiddleware : OwinMiddleware 
{ 
    public override async Task Invoke(IOwinContext context) 
    { 
     try 
     { 
      await Next.Invoke(context); 
     } 
     catch (OperationCanceledException) when (context.Request.CallCancelled.IsCancellationRequested) 
     { 
      //swallow user-agent cancelling request. 
      _log.Trace($"client disconnected on request for: {context.Request.Path}."); 
     } 
     catch (Exception ex) 
     { 
      _log.Error(ex); 
      context.Response.StatusCode = (int) HttpStatusCode.InternalServerError; 
      context.Response.ReasonPhrase = "Internal Server Error"; 
     } 
    } 
} 
Các vấn đề liên quan