W ciągu ostatnich kilku dni testowałem nowe funkcje .net 4.5 i c # 5.
Podoba mi się jego nowe funkcje async / await. Wcześniej korzystałem z BackgroundWorker do obsługi dłuższych procesów w tle z responsywnym interfejsem użytkownika.
Moje pytanie brzmi: kiedy mam te fajne nowe funkcje, kiedy powinienem używać async / await, a kiedy BackgroundWorker ? Jakie są typowe scenariusze dla obu?
Odpowiedzi:
async / await jest przeznaczony do zastępowania konstrukcji, takich jak
BackgroundWorker
. Chociaż z pewnością możesz go użyć, jeśli chcesz, powinieneś móc używać async / await, wraz z kilkoma innymi narzędziami TPL, do obsługi wszystkiego, co tam jest.Ponieważ oba działają, sprowadza się to do osobistych preferencji, kiedy używasz. Co jest dla ciebie szybsze ? Co jest dla ciebie łatwiejsze do zrozumienia?
źródło
async
/await
również umożliwia programowanie asynchroniczne bez wątków puli wątków.To prawdopodobnie TL; DR dla wielu, ale myślę, że porównywanie
await
z porównaniemBackgroundWorker
jest jak porównywanie jabłek i pomarańczy, a moje przemyślenia na ten temat są następujące:BackgroundWorker
ma na celu modelowanie pojedynczego zadania, które chcesz wykonać w tle, w wątku puli wątków.async
/await
to składnia asynchronicznego oczekiwania na operacje asynchroniczne. Te operacje mogą, ale nie muszą, używać wątku puli wątków lub nawet używać dowolnego innego wątku . Więc to jabłka i pomarańcze.Na przykład możesz wykonać następujące czynności
await
:Ale prawdopodobnie nigdy nie modelowałbyś tego w pracy w tle, prawdopodobnie zrobiłbyś coś takiego w .NET 4.0 (przed
await
):Zwróć uwagę na rozłączność rozdysponowania w porównaniu między dwiema składniami i tym, jak nie możesz użyć
using
bezasync
/await
.Ale nie zrobiłbyś czegoś takiego z
BackgroundWorker
.BackgroundWorker
służy zwykle do modelowania pojedynczej długotrwałej operacji, na którą nie chcesz mieć wpływu na responsywność interfejsu użytkownika. Na przykład:Naprawdę nie ma tam nic, z czym możesz użyć async / await,
BackgroundWorker
tworzy wątek dla Ciebie.Teraz możesz zamiast tego użyć TPL:
W takim przypadku
TaskScheduler
tworzy wątek dla Ciebie (zakładając domyślnyTaskScheduler
) i może użyćawait
w następujący sposób:Moim zdaniem główne porównanie dotyczy tego, czy zgłaszasz postępy, czy nie. Na przykład możesz mieć
BackgroundWorker like
to:Ale nie poradziłbyś sobie z niektórymi z tego, ponieważ przeciągnąłbyś i upuść komponent roboczy w tle na powierzchnię projektu formularza - coś, czego nie możesz zrobić z
async
/await
iTask
... tj. Wygrałeś ” Utwórz obiekt ręcznie, ustaw właściwości i ustaw programy obsługi zdarzeń. chcesz wypełnić tylko w organizmie zDoWork
,RunWorkerCompleted
iProgressChanged
obsługi zdarzeń.Jeśli „przekonwertowałeś” to na async / await, zrobiłbyś coś takiego:
Bez możliwości przeciągania komponentu na powierzchnię Projektanta, tak naprawdę to czytelnik decyduje, co jest „lepsze”. Ale to jest dla mnie porównanie między
await
aBackgroundWorker
, a nie tym, czy można czekać na wbudowane metody, takie jakStream.ReadAsync
. np. jeśli używaszBackgroundWorker
zgodnie z przeznaczeniem, konwersja do użycia może być trudnaawait
.Inne przemyślenia: http://jeremybytes.blogspot.ca/2012/05/backgroundworker-component-im-not-dead.html
źródło
var t1 = webReq.GetResponseAsync(); var t2 = webReq2.GetResponseAsync(); await t1; await t2;
. Który czekałby na dwie równoległe operacje. Oczekiwanie jest znacznie lepsze w przypadku zadań asynchronicznych, ale sekwencyjnych, IMO ...await Task.WhenAny(t1, t2)
możesz coś zrobić, gdy jedno z zadań zostanie ukończone jako pierwsze. Prawdopodobnie będziesz potrzebować pętli, aby upewnić się, że inne zadanie również się zakończyło. Zwykle chcesz wiedzieć, kiedy kończy się określone zadanie, co prowadzi do napisania kolejnychawait
s.To jest dobre wprowadzenie: http://msdn.microsoft.com/en-us/library/hh191443.aspx Sekcja Wątki jest właśnie tym, czego szukasz:
źródło
BackgroundWorker jest jawnie oznaczony jako przestarzały w .NET 4.5:
Artykuł MSDN „Programowanie asynchroniczne przy użyciu funkcji Async and Await (C # i Visual Basic)” mówi:
AKTUALIZACJA
„dla operacji związanych z IO, ponieważ kod jest prostszy i nie musisz się wystrzegać warunków wyścigu”. Jakie warunki wyścigu mogą wystąpić, czy możesz podać przykład? "
To pytanie należało umieścić w osobnym poście.
Wikipedia dobrze wyjaśnia warunki wyścigów . Niezbędną częścią tego jest wielowątkowość i ten sam artykuł MSDN Asynchronous Programming with Async and Await (C # and Visual Basic) :
Oznacza to, że „Słowa kluczowe async i await nie powodują tworzenia dodatkowych wątków”.
O ile pamiętam moje własne próby, gdy studiowałem ten artykuł rok temu, jeśli uruchomiłeś i bawiłeś się próbką kodu z tego samego artykułu, możesz wpaść w sytuację, że jego wersje nie-asynchroniczne (możesz spróbować przekonwertować to do siebie) blokować na czas nieokreślony!
Ponadto, aby znaleźć konkretne przykłady, możesz przeszukać tę witrynę. Oto kilka przykładów:
źródło