Вопрос:

Является ли Task.Result таким же, как .GetAwaiter.GetResult ()?

c# async-await

72077 просмотра

6 ответа

32068 Репутация автора

Недавно я читал некоторый код, который использует много асинхронных методов, но иногда необходимо выполнять их синхронно. Код делает:

Foo foo = GetFooAsync(...).GetAwaiter().GetResult();

Это так же, как

Foo foo = GetFooAsync(...).Result;

?

Автор: Jay Bazuzi Источник Размещён: 24.06.2013 08:28

Ответы (6)


135 плюса

16710 Репутация автора

Довольно много. Одно небольшое отличие: если произойдет Taskсбой, GetResult()просто сгенерирует исключение, вызванное напрямую, а Task.Resultсгенерирует AggregateException. Тем не менее, какой смысл использовать любой из них, когда это async? В 100 раз лучше использовать await.

Кроме того, вы не должны использовать GetResult(). Он предназначен только для использования компилятором, а не для вас. Но если вы не хотите раздражать AggregateException, используйте его.

Автор: It'sNotALie. Размещён: 24.06.2013 08:34

64 плюса

673 Репутация автора

https://github.com/aspnet/Security/issues/59

«Последнее замечание: вам следует избегать использования Task.Resultи Task.Waitкак можно большего числа случаев, когда они всегда инкапсулируют внутреннее исключение в, AggregateExceptionи заменять сообщение универсальным (произошла одна или несколько ошибок), что затрудняет отладку. Даже если синхронная версия не должна не используйте это часто, вы должны настоятельно рассмотреть возможность использования Task.GetAwaiter().GetResult()вместо этого. "

Автор: scyuo Размещён: 31.07.2015 08:59

83 плюса

1560 Репутация автора

Task.GetAwaiter().GetResult()предпочтительнее, Task.Waitи Task.Resultпотому что он распространяет исключения, а не заключает их в AggregateException. Тем не менее, все три метода вызывают потенциальные проблемы взаимоблокировки, и их следует избегать в пользу async/await.

Приведенная ниже цитата объясняет, почему, Task.Waitа Task.Resultне просто содержит поведение распространения исключений Task.GetAwaiter().GetResult()(из-за «очень высокой полосы совместимости»).

Как я упоминал ранее, у нас очень высокая планка совместимости, и поэтому мы избежали серьезных изменений. Таким образом, Task.Waitсохраняет свое первоначальное поведение всегда обертывания. Однако вы можете столкнуться с некоторыми сложными ситуациями, когда вам нужно поведение, аналогичное используемому синхронной блокировкой Task.Wait, но где вы хотите, чтобы исходное исключение распространялось не развернутым, а не заключенным в AggregateException. Чтобы достичь этого, вы можете напрямую нацелить ожидающего задания. Когда вы пишете « await task;», компилятор переводит это в использование Task.GetAwaiter()метода, который возвращает экземпляр, у которого есть GetResult()метод. При использовании в отказавшей Задаче GetResult()будет распространяться исходное исключение (таким образом « await task;» получает свое поведение). Таким образом, вы можете использоватьtask.GetAwaiter().GetResult()”, Если вы хотите напрямую вызвать эту логику распространения.

https://blogs.msdn.microsoft.com/pfxteam/2011/09/28/task-exception-handling-in-net-4-5/

« GetResult» На самом деле означает «проверить задачу на наличие ошибок»

В общем, я стараюсь изо всех сил избегать синхронной блокировки асинхронной задачи. Однако есть несколько ситуаций, когда я нарушаю это правило. В этих редких случаях мой предпочтительный метод заключается в том, GetAwaiter().GetResult()что он сохраняет исключения задач, а не заключает их в AggregateException.

http://blog.stephencleary.com/2014/12/a-tour-of-task-part-6-results.html

Автор: Nitin Agarwal Размещён: 22.07.2016 03:27

28 плюса

8070 Репутация автора

Другое различие заключается в том, что когда asyncфункция возвращает результат Taskвместо того, Task<T>чтобы использовать

GetFooAsync(...).Result;

В то время как

GetFooAsync(...).GetAwaiter().GetResult();

еще работает.

Я знаю, что пример кода в вопросе для случая Task<T>, однако вопрос задается в целом.

Автор: Nuri Tasdemir Размещён: 03.03.2017 11:47

4 плюса

17790 Репутация автора

Как уже упоминалось, если вы можете использовать await. Если вам нужно выполнить код синхронно, как вы упомянули .GetAwaiter().GetResult(), .Resultили .Wait()существует риск возникновения тупиковых ситуаций, как многие говорили в комментариях / ответах. Поскольку большинство из нас любят вкладыши, вы можете использовать их для.Net 4.5<

Получение значения с помощью асинхронного метода:

var result = Task.Run(() => asyncGetValue()).Result;

Синхронный вызов асинхронного метода

Task.Run(() => asyncMethod()).Wait();

Никаких проблем с блокировкой не возникнет из-за использования Task.Run.

Источник:

https://stackoverflow.com/a/32429753/3850405

Автор: Ogglas Размещён: 24.01.2019 03:12

0 плюса

93 Репутация автора

В случае сбоя задачи исключение выдается повторно, когда код продолжения вызывает awaiter.GetResult (). Вместо вызова GetResult мы могли бы просто получить доступ к свойству Result антецедента. Преимущество вызова GetResult состоит в том, что в случае сбоя задачи исключение генерируется напрямую, без включения в Aggre gateException, что позволяет создавать более простые и чистые блоки перехвата.

Для неуниверсальных задач GetResult () имеет возвращаемое значение void. Его полезная функция - исключать исключения.

источник: c # 7.0 в двух словах

Автор: Ali Abdollahi Размещён: 13.06.2019 09:05
Вопросы из категории :
32x32