2015-07-04 15 views
8

Jak rozumiem, Task.Yield na początku metody zmusi dzwoniącego, aby kontynuował, jeśli nie oczekuje na metodę. Tymczasem Task.Run i ConfigureAwait(false)both uruchom zadanie na nowym wątku puli wątków, co ponownie zmusi wywołującego do kontynuacji, jeśli nie oczekuje na metodę.Jaka jest różnica między Task.Yield, Task.Run i ConfigureAwait (false)?

Nie mogę zrozumieć różnicy między Task.Yield a uruchomieniem nowego wątku puli wątków, ponieważ zaraz po tym, jak powróci on do wywołującego, będzie kontynuował wykonywanie reszty metody, która jest w zasadzie tym samym.

This postu sugeruje, że Yield i Task.Factory.StartNew (co jest naprawdę stara wersja Task.Run) można stosować zamiennie, co wydaje się dziwne dla mnie.

+1

Task.Run = Task.Factory.StartNew – hungndv

+0

@hungndv 'Task.Run' to' Task.Factory.StartNew', ale w domyślnym harmonogramie zadań (harmonogram zadań puli wątków). 'Task.Factory.StartNew' bez określania harmonogramu zadań wybierze bieżący harmonogram zadań, który może nie być domyślny. Może to być na przykład program do planowania zadań interfejsu użytkownika. 'Task.Run' zawsze wykonuje się w wątku. Tak więc 'Task.Run' jest szczególnym przypadkiem' Task.Factory.StartNew', i ** not ** jego nowej wersji –

Odpowiedz

6

Task.Yield nie jest zamiennikiem dla Task.Run i to nie ma nic wspólnego z Task.ConfigureAwait.

  • Task.Yield - Generuje oczekiwane zakończenie tuż po sprawdzeniu, czy jest ukończone.
  • ConfigureAwait(false) - Generuje oczekiwanie na zadanie, które lekceważy przechwycone SynchronizationContext.
  • Task.Run - Wykonuje delegata na wątku ThreadPool.

Task.Yield jest inny niż ConfigureAwait tym, że jest awaitable samą w sobie, nie konfigurowalnym owinięcie drugiego awaitable (czyli Task). Kolejna różnica polega na tym, że Task.Yield kontynuuje przechwytywany kontekst.

Task.Run różni się od obu, ponieważ zabiera delegata i uruchamia go na ThreadPool, można go używać z ConfigureAwait(false) lub bez. Aby wymusić punkt asynchroniczny, nie należy go wymieniać na

zamiast na Task.Run. Po osiągnięciu oczekiwanej metody asynchronicznej sprawdza, czy zadanie (lub inne wyczekiwane) zostało już zakończone, a jeśli tak, to kontynuuje synchronicznie. Task.Yield zapobiega takiemu zdarzeniu, dlatego jest to przydatne do testowania.

Innym zastosowaniem jest użycie metod interfejsu użytkownika, w których nie chcesz używać pojedynczego wątku interfejsu użytkownika, wstawiasz punkt asynchroniczny, a reszta jest planowana do wykonania w późniejszym czasie.

+3

'Task.Yield' nie działa w celu uniknięcia dławienia interfejsu użytkownika, ponieważ kolejki komunikatów UI mają priorytet (a kontynuacje zawsze mają pierwszeństwo przed' WM_PAINT'). –

+0

Również nigdy nie chcesz malować tak szybko, jak to tylko możliwe. Spala jeden rdzeń za nic. – usr

+0

@StephenCleary: kto publikuje kontynuacje w kolejce komunikatów interfejsu użytkownika? Może się to zdarzyć tylko wtedy, gdy niektóre BeginInvoke zostanie wywołane w pewnym momencie –

5

Task.Yield kontynuuje bieżący kontekst synchronizacji lub bieżący TaskScheduler, jeśli jest obecny. Task.Run tego nie robi. Zawsze używa puli wątków.

Na przykład Task.Yield pozostanie w wątku interfejsu użytkownika.

Należy unikać Task.Yield. Jego semantyka jest mniej jasna. Połączona odpowiedź to zapach kodu.

+0

Dobra wskazówka dotycząca użycia 'TaskScheduler.Current' przez' Task. Yield' - kolejna budząca wątpliwości decyzja projektowa zespołu TPL. I nie można tego uzasadnić względami kompatybilności .NET 4.0, ponieważ nie ma 'Task.Yield' w .NET 4.0. – Noseratio

+0

@Noseratio Jak to jest wątpliwe? 'await' kontynuuje przechwycony kontekst, chyba że wyraźnie podano inaczej, co jest bezpieczną wartością domyślną. Dlaczego powinno być inaczej z 'Task.Yield'. – i3arnon

+0

@ i3arnon, nie kwestionuję zachowania 'Task.Yield', gdy kontekst synchronizacji jest obecny. Ale pod nieobecność jednego, kwestionuję użycie 'TaskScheduler.Current' kontra' TaskScheduler.Default'. Mocno wierzę, że ta ostatnia powinna była zostać użyta, tak jak w przypadku 'Task.Run'. – Noseratio

Powiązane problemy