2015-12-31 13 views
11

Próbuję znaleźć najlepszą praktykę dla jednego z moich projektów. Jest to typowa aplikacja WPF z interfejsem użytkownika, który wyświetla listę elementów i istnieje usługa danych, która zwraca wynik.Async await vs GetAwaiter(). GetResult() i wywołanie zwrotne

Dzwonimy do usługi asynchronicznie, aby nie blokować interfejsu użytkownika. Mamy 2 opcje przed nami:

  1. Korzystanie ASYNC czekają wyszukiwane To wymaga oznakowania wszystkich metod ASYNC od kliknięcia przycisku całą drogę do obsługi warstwy (klasa po stronie klienta, który sprawia, że ​​połączenia HTTP do serwera) i dowolną metodę pomiędzy. Podejście to działa dobrze, inne niż kwestia propagowania asynchronicznie wszędzie

  2. Zastosowanie awaiter i zwrotna W tym podejściu klient UI nazywa warstwie usług i przechodzi wywołania zwrotnego do warstwy usług, warstwa usługa owija połączenia HTTP do serwer w zadaniu i użyj GetAwaiter(). GetResult(), po zakończeniu wywołania http wywołuje wywołanie zwrotne przekazane przez klienta interfejsu użytkownika. W tym przypadku żadna metoda nie musi oznaczać asynchronizacji, ale nie jest do końca pewna co do użycia funkcji GetAwaiter()

    Task.Run (async() => // oczekiwanie na połączenie http, wywołanie zwrotne) .GetAwaiter(). GetResult ();

Ja tylko próbuje dowiedzieć się, co jest lepsze podejście i jeśli są jakieś problemy z obu podejścia, które powinny być świadomy

+1

Jestem prawie pewien, że drugie podejście może czasami prowadzić do martwych zamków. Wiem, ponieważ napotkałem coś podobnego podczas pracy z Windows Universal. – Felype

+0

Istnieje również kwestia wyjątków. Wiem, że przy pełnej asynchronicznej implementacji na końcu pojawia się 'AggregateException', ale nie mam pojęcia, co dzieje się z wyjątkami w metodzie' GetAwaiter'. – Eris

+0

@Eris Kiedy oczekujesz, że nie dostaniesz 'AggregateException'. Otrzymujesz wewnętrzny wyjątek. To samo dzieje się z 'GetResult'. – i3arnon

Odpowiedz

16

należy użyć async i await słowa kluczowe całą drogę lub w ogóle nie powinieneś używać asynchronicznych.

Twoja druga opcja nie jest tak naprawdę asynchroniczna. Wywołuje operację asynchroniczną i blokuje ją synchronicznie z task.GetAwaiter().GetResult(). Oprócz tego, że jest bardzo skomplikowany, nie jest asynchroniczny i może prowadzić do zakleszczeń.

+0

Czy masz więcej informacji podstawowych na temat przyczyn zakleszczeń? Doświadczyłem tego również, ale szukam bardziej szczegółowych informacji o tym, dlaczego tak się dzieje i jak to działa. –

+2

@FrederikGheysels http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html – i3arnon

+0

Brzmi jak świetna rada, z tym wyjątkiem, że utknąłem z tego API z Azure Active Directory (TokenCache), który wymaga operacji synchronicznych. Nie można powrócić z "BeforeAccessNotification", dopóki nie zostanie odczytany pamięci podręcznej i nie można wrócić z "AfterAccessNotification", dopóki nie zostanie zapisany pamięci podręcznej. Jaka jest twoja rada, kiedy jesteś zmuszony do synchronicznego API i potrzebujesz dostępu do pliku? –