Result
само по себе не вызывает тупик .Он вызывает взаимоблокировку при вызове из однопоточного контекста , если есть await
для этой задачи, которая также нуждается в этом контексте.
Подробнее :
await
по умолчанию захватывает контекст и возобновляет работу в этом контексте.(Вы можете использовать ConfigureAwait(false)
, чтобы переопределить это поведение по умолчанию и продолжить работу в потоке пула потоков.) Result
блокирует текущий поток до тех пор, пока Task
не будет завершен.(Вы можете использовать await
для асинхронного использования задачи, чтобы избежать блокировки потока.) - Некоторые контексты являются однопоточными;т.е. они допускают только один поток за раз.Например, ASP.NET Classic имеет однопоточный контекст запроса.(Вы можете использовать
Task.Run
для запуска кода в потоке пула потоков с контекстом пула потоков, который не является однопоточным контекстом.)
Итак, чтобы получить взаимоблокировку, вам нужноиметь await
, который захватывает однопоточный контекст, а затем блокировать поток внутри этого контекста (например, вызывая Result
для этой задачи).Для await
требуется контекст для завершения Task
, но контекст допускает только один поток за раз, а Result
удерживает поток заблокированным в этом контексте до завершения Task
.
В вашем примере вы вызываете GetJsonAsync
внутри Task.Run
, который запускает его в пуле потоков.Таким образом, await
в GetJsonAsync
(и await
в делегате, переданном в Task.Run
) захватывает контекст пула потоков, а не контекст потока запросов ASP.NET.Затем ваш код вызывает Result
, что блокирует поток запроса ASP.NET (и его контекст), но, поскольку await
этот контекст не нужен, тупика нет.