Мой метод возвращается 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дает вам более красивые стеки, если вам это нужно.