У чому різниця між .Wait () та .GetAwaiter (). GetResult ()?


88

Мій метод повертається Task. Я хочу почекати, поки все закінчиться. Що я повинен використовувати .Wait()або .GetAwaiter().GetResult()? Яка різниця між ними?

Відповіді:


107

І те, і інше - це синхронне очікування результату операції (і вам слід уникати таких, якщо це можливо).

Різниця полягає головним чином у обробці винятків. З Wait, трасування стека винятків є незмінним і представляє фактичний стек на момент виключення, тому, якщо у вас є фрагмент коду, який працює на потоці пулу потоків, у вас буде такий стек, як

ThreadPoolThread.RunTask
YourCode.SomeWork

З іншого боку, .GetAwaiter().GetResult()буде перероблено трасування стека, щоб врахувати весь асинхронний контекст, ігноруючи, що деякі частини коду виконуються в потоці інтерфейсу користувача, а деякі - у потоці ThreadPool, а деякі - просто асинхронним введенням-виведенням. Отже, ваш стек трасування відображатиме синхронний крок вашого коду :

TheSyncMethodThatWaitsForTheAsyncMethod
YourCode.SomeAsyncMethod
SomeAsync
YourCode.SomeWork

Це, як правило, робить сліди стеків винятків набагато кориснішими, м’яко кажучи. Ви можете бачити, де YourCode.SomeWorkбуло викликано в контексті вашої програми , а не "фізичний спосіб її запуску".

Приклад того, як це працює, є в довідковому джерелі (звичайно, поза договірним договором).


6
Task.GetAwaiter () повертає TaskAwaiter . Однак документ для TaskAwaiter.GetResult () радить: "Цей API підтримує інфраструктуру продукту і не призначений для використання безпосередньо з вашого коду." Чи можете ви прокоментувати?
DavidRR

23
@DavidRR Все TaskAwaiterце є деталлю реалізації. З іншого боку, механізм очікуваного / очікуючого задокументований і використовує набір качок - GetAwaiterце awaitяк GetEnumeratorє, foreachчи Disposeє using. Все це визначено в специфікації C # незалежно від конкретного використовуваного очікувача - зауважте, що Task.GetAwaiter"призначений для використання компілятором, а не для використання в коді програми". Але справа в тому, що передбачуване використання полягає у виконанні await, а не Wait()ні, GetAwaiter().GetResult()- але GetResultнадає вам приємніші стеки, якщо вам це потрібно.
Луан
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.