2016-02-18 9 views
5

Zajmuję się tworzeniem aplikacji web-api, która pobiera dane z klienta i zapisuje je do późniejszego wykorzystania. Teraz mam system zewnętrzny, który musi znać wszystkie zdarzenia, dlatego chcę skonfigurować komponent powiadomień w moim interfejsie webowym.webapi 2 - jak poprawnie wywołać długotrwałą metodę async/w nowym wątku i zwrócić odpowiedź na klienta

Po zapisaniu danych wykonuję metodę SendNotification(message) w moim nowym komponencie. Tymczasem nie chcę, aby mój klient czekał, a nawet wiedział, że wysyłamy powiadomienia, więc chcę jak najszybciej zwrócić odpowiedź moim klientom na odpowiedź 201 Created/200 OK.

Tak, jest to scenariusz polegający na pożarze i zapomnieniu. Chcę, aby komponent powiadomień obsługiwał wszystkie wyjątki (jeśli powiadomienie nie powiedzie się, klient api naprawdę nie przejmuje się wcale).

Próbowałem używać async/await, ale to nie działa w web-api, ponieważ po zakończeniu wątku żądania, operacja asynchroniczna również to robi.

Więc przyjrzałem się Task.Run().

Mój kontroler wygląda tak:

public IHttpActionResult PostData([FromBody] Data data) { 
    _dataService.saveData(data); 
    //This could fail, and retry strategy takes time. 
    Task.Run(() => _notificationHandler.SendNotification(new Message(data))); 
    return CreatedAtRoute<object>(...); 
} 

A metoda w moim NotificationHandler

public void SendNotification(Message message) { 
    //..send stuff to a notification server somewhere, syncronously. 
} 

Jestem stosunkowo nowy w C# świata, a ja nie wiem, czy istnieje bardziej elegancki (lub właściwy) sposób robienia tego. Czy są jakieś pułapki przy użyciu tej metody?

+0

Dlaczego nie możesz korzystać z asynchronicznych/oczekujących? Ramy powinny się tym zająć. – timothyclifford

+0

Jeśli wykonuję funkcję 'SendNotification()' zwracającą 'asynchroniczne zadanie', muszę' czekać' na wywołanie w mojej klasie kontrolera, a kiedy wrócę do kontrolera, zanim moja metoda asynchroniczna zostanie zakończona, metoda asynchroniczna kończy się, i nigdy się nie kończy. –

+0

To brzmi jak złe zachowanie. Jeśli używasz asynchronizacji, nie powinno to kończyć się przed jej użyciem. Czy możesz dołączyć kod asynchronizowany? – timothyclifford

Odpowiedz

4

To naprawdę zależy od tego, jak długo. Czy sprawdziłeś możliwość QueueBackgroundWorkItem jako szczegółową here. Jeśli chcesz zaimplementować bardzo szybki ogień i zapomnieć, możesz również rozważyć kolejkę, aby wysyłać te wiadomości, aby móc natychmiast wrócić z kontrolera. Trzeba by mieć coś, co odpytuje kolejkę i wyśle ​​powiadomienia tj. Zaplanowane zadanie, usługa Windows itp. IIRC, jeśli IIS przetwarza podczas zadania, proces jest zabijany, podczas gdy z QueueBackgroundWorkItem jest okres karencji, dla którego ASP. Sieć pozwoli, aby element pracy zakończył pracę.

+0

Dzięki za twój wkład. Dam mu wir. –

1

Chciałbym rzucić okiem na Hangfire. Jest dość łatwy w konfiguracji, powinien być w stanie działać w ramach procesu ASP.NET i można go łatwo migrować do samodzielnego procesu w przypadku, gdy obciążenie IIS nagle wzrasta. Eksperymentowałem z Hangfire jakiś czas temu, ale w trybie autonomicznym. Ma wystarczającą liczbę dokumentów i łatwy do zrozumienia interfejs API.