Мой метод возвращается Task
. Я хочу подождать, пока он не закончится. Что мне использовать
.Wait()
или .GetAwaiter().GetResult()
? В чем разница между ними?
Мой метод возвращается Task
. Я хочу подождать, пока он не закончится. Что мне использовать
.Wait()
или .GetAwaiter().GetResult()
? В чем разница между ними?
Ответы:
Оба являются синхронным ожиданием результата операции (и вам следует избегать его, если это возможно).
Разница в основном заключается в обработке исключений. С Wait
, трассировка стека исключений не изменяется и представляет фактический стек во время исключения, поэтому, если у вас есть фрагмент кода, который выполняется в потоке пула потоков, у вас будет стек вида
ThreadPoolThread.RunTask
YourCode.SomeWork
С другой стороны, .GetAwaiter().GetResult()
будет переработана трассировка стека, чтобы учесть весь асинхронный контекст, игнорируя, что некоторые части кода выполняются в потоке пользовательского интерфейса, а некоторые - в потоке ThreadPool, а некоторые представляют собой просто асинхронный ввод-вывод. Таким образом, ваша трассировка стека будет отражать синхронный шаг по вашему коду :
TheSyncMethodThatWaitsForTheAsyncMethod
YourCode.SomeAsyncMethod
SomeAsync
YourCode.SomeWork
Это, мягко говоря, делает трассировку стека исключений намного более полезной. Вы можете видеть, где YourCode.SomeWork
был вызван в контексте вашего приложения , а не «физический способ его запуска».
Пример того, как это работает, можно найти в справочном источнике (разумеется, вне договора).
TaskAwaiter
это деталь реализации. С другой стороны, механизм awaitable / awaiter документирован, и использует утиную типизацию - GetAwaiter
это , await
как GetEnumerator
это foreach
или Dispose
это using
. Все это определено в спецификации C # независимо от конкретного используемого средства ожидания - обратите внимание, что Task.GetAwaiter
оно «предназначено для использования компилятором, а не для использования в коде приложения». Но дело в том, что предполагаемое использование состоит в том, чтобы делать await
, а не Wait()
или GetAwaiter().GetResult()
- но GetResult
дает вам более красивые стеки, если вам это нужно.