2015-05-08 11 views
7

biegnę Owin własnym gospodarzem Web API, z typowym kontrolerze tak:Async Web Api Controller - Jak radzić sobie z odwołaniami?

[HttpGet] 
    [Route("refresh/{secId}")] 
    [ResponseType(typeof(int))] 
    public async Task<IHttpActionResult> RefreshElement(int secId) 
    { 
     var count = await _db.Refresh(secId); 

     if (count == 0) 
      return NotFound(); 

     return Ok(count); 
    } 

Zakładając _db.Refresh() jest długo działa (kilka sekund), a czasami zgłasza wyjątek.

Problem udało mi się odtworzyć to:

  • Zapytanie uderza metody _db.Refresh zostanie wystrzelone
  • Zamówienie jest anulowane (gniazdo zamknięte)

Wynik parametru _db.Refresh nie jest już oczekiwany - ponieważ widzę, że zwraca wyjątek, pojawia się on po niezaobserwowanym działaniu wyjątku TPL, gdy zadaniem jest GCd ...

Mayb Ze względu na takie interakcje zespół .net zmienił nieobsługiwaną politykę wyjątków, aby nie zburzyć procesów (myślę, że 4.5) ... więc jaki jest dobry wzór tego problemu? W szczególności dla samoobsługowej WebApi używającej OWIN-a, ponieważ wciąż loguję niezobowiązujące wyjątki jako FATAL :)

Mogę sprawić, że _db.Refresh() otrzyma token anulowania, ale jak/kiedy ustawię token anulowania dla rozłączeń/anulowań w webapi hosta?

Odpowiedz

0

Możesz obsłużyć czas żądania, wykonując samodzielnie oprogramowanie pośrednie.

IOwinContext ma właściwość Request która sama posiada CancellationToken nazwie CallCancelled, które mogą być odpytywany, aby sprawdzić, czy żądanie zostało anulowane:

public class CancellationAwareOwinMiddleware : OwinMiddleware 
{ 
    public async Task Invoke(IOwinContext owinContext) 
    { 
     try 
     { 
       await Next.Invoke(owinContext); 
     } 
     catch (TaskCanceledException) 
     { 
      // Handle cancellation. 
     } 
     catch (Exception e) 
     { 
      if (owinContext.Request.CallCancelled.IsCancellationRequested) 
      { 
       // Handle cancellation. 
      } 
     } 
    } 
} 

Uwaga ogólna klauzula Wyjątkiem jest tam, bo nie jestem pewien OWIN rzuci TCE, gdy żądanie tge zostanie anulowane, więc polub token, aby mieć pewność.

Edit:

Jak @usr wskazał mi, to rozwiązanie będzie obsługiwać przypadek outter Task dzieje niepostrzeżenie, i to było dość duże założenie robiłem. Jeśli to wewnętrzne zadanie, muszę przemyśleć to rozwiązanie.

+0

Czy to naprawdę rozwiązuje problem, że zadanie zwrócone przez "RefreshElement" może nigdy nie zostać zaobserwowane? – usr

+0

@usr Pytanie brzmi, które 'zadanie' nie będzie obserwowane, wewnętrzne zadanie lub wyjście. Ale masz rację, nie jestem pewien, dlaczego założyłem, że to było wyjście. –

+0

Myślę, że wewnętrzne zadanie będzie obserwowane przez oczekujące, które wciąż trwa. To nie jest anulowane. W rzeczywistości "RefreshElement" nigdy nie jest anulowane. – usr

12

Być może nie w pełni odpowiedzieć na to pytanie, ale uważam, że odpowiada na tę ostatnią część:

mogę _db.Refresh() podjąć w znak rezygnacji, ale jak/kiedy mogę ustawić token anulowania dla rozłączeń/odwołań w webapi hosta?

Jeśli dodasz parametr CancellationToken do swojej metody akcji, framework dostarczy jeden, gdy go wywoła.

[HttpGet] 
[Route("refresh/{secId}")] 
[ResponseType(typeof(int))] 
public async Task<IHttpActionResult> RefreshElement(
    int secId, CancellationToken cancellationToken) 
{ 
    var count = await _db.Refresh(secId, cancellationToken); 

    if (count == 0) 
     return NotFound(); 

    return Ok(count); 
} 

Uwaga jednak, że nadal istnieje małe okno możliwości, w którym klient mógł odłączyć przed metodę wyjścia działań, w tym przypadku nadal będzie występować Twój TPL niepostrzeżenie wyjątkiem.

+0

Anulowanie może wystąpić tuż po ostatnim czasie Odśwież sprawdza token, ale zanim się nie powiedzie. To tylko zmniejsza okno możliwości. To nie jest poprawka. – usr

+0

@usr Zdaję sobie sprawę z problemu, który rozwiązuje twój komentarz i inna odpowiedź. Wyjaśniłem, na którą część pytania odpowiadam. –

+0

@usr Zastanawiam się, czy framework wie, aby obserwować Zadanie w przypadku, gdy Token Anulowania został anulowany podczas żądania? –

Powiązane problemy