2016-12-07 51 views
5

Mam projekt C# ASP.Net (inny niż MVC), który używa długo-sondowania Ajax Comet. Strona internetowa wywołuje HTTP do punktu końcowego obsługiwanego przez klasę implementującą IHttpAsyncHandler.Jak zrobić C# Ajax Comet przez WebAPI2?

Jeśli na stronie internetowej nie ma nic do zgłaszania (w ciągu kilku sekund), wysyłana jest pusta odpowiedź HTTP, a strona internetowa ponownie wywołuje. Jeśli jest coś do wysłania, a aktualizacja jest wysyłana, a strona internetowa przetwarza i ponownie wywołuje. Jest to dość standardowa technologia push i działa bardzo dobrze.

Teraz próbuję dodać punkty końcowe API, używając WebAPI2, non-MVC. Mam działające kontrolery synchroniczne, oparte na klasie ApiController.

Chciałbym skonfigurować technologię push dla wywołań interfejsu API, aby użytkownicy interfejsu API nie musieli sondować aktualizacji.

Podobnie jak w powyższej metodzie, wywołanie API punktu końcowego jest odbierane, a kontekst jest zapisywany. Jeśli upłynął limit czasu, połączenie zostanie zwrócone puste, a dzwoniący powinien ponownie zadzwonić. Jeśli aktualizacje danych w określonym limicie czasu, dane są zwracane do osoby dzwoniącej, a dzwoniący powinien ponownie zadzwonić i czekać na kolejne aktualizacje.

Problem polega na tym, że wydaje się, że nie ma asynchronicznej wersji ApiController. Celem jest uwolnienie wątku obsługującego wywołanie API, zwrócenie go do puli, a gdy dostępne są dane lub upłynął limit czasu, wątek roboczy jest używany do zwracania odpowiedzi.

Jak skonfigurować apiController, aby wątek przetwarzający połączenie został zwolniony, kontekst połączenia jest przechowywany i mogę wysłać odpowiedź na połączenie w późniejszym czasie?

+1

Dlaczego nie używasz SignalR? –

+0

Długie głosowanie działa i jest bardzo wydajne, szczególnie w przypadku złej jakości połączeń. Działa dobrze. Po prostu muszę dowiedzieć się, jak rozłączyć połączenie WebAPI2 tak, jakby było to standardowe żądanie HTTP. –

Odpowiedz

2

Można użyć async/czekają aby osiągnąć to, co chcesz, to znaczy:

[HttpPost] 
public async Task<HttpResponseMessage> LongRunningOperation([FromBody]Input obj) 
{ 
    // Do what ever you need with input data   

    await WaitForEvent();   

    // Do what ever you need to return a response 

    return someResponse; 
} 

W tym przykładzie metoda Web API jest zadeklarowana jako async aw jej ciele await operator został użyty, aby powrócić do wątku na basenie .

Założę się, że w celu wdrożenia komety wykorzystujesz jakieś zdarzenia. O ile pamiętam wiele lat temu użyłem ManualResetEvent, aby to zrobić. Jednak może to być cokolwiek innego.

Ważne jest, aby metoda WaitForEvent zwracała coś nieoczekiwanego. Innymi słowy, ManualResetEvent lub inny uchwyt oczekiwania powinien być zawijany w zadaniu. Możesz to zrobić za pomocą metody AsyncFactory.FromWaitHandle.

Warto również przeczytać ten discussion o asyn/oczekuj w kontekście Web API.

+0

Używam zdarzeń gdzie indziej, do normalnych wątków, ale nie myślałem, aby użyć ich tutaj. Spróbuję tego, dzięki za post. –

+0

Dla komety strony obecnie używam asynchronicznych procedur obsługi HTTP. Tworzy wyprowadzony obiekt AsyncResult, który opakowuje kontekst http. Obiekty AsyncResult są przechowywane w kolekcji do momentu upłynięcia limitu czasu lub nadejścia danych. Gdy tak się stanie, żądanie kontekstowe zostanie zakończone. Klient doświadcza pustej odpowiedzi po przekroczeniu limitu czasu lub odpowiedzi z danymi w pewnym momencie przed upływem limitu czasu (np. Klasyczna kometa), i w każdym przypadku, pętli klienta i ponownych żądań. Klient jest prawie zawsze podłączony, pasywnie czekając na dane, nie wiążąc nici. –