Посмотрите пример в здесь , у Стивена есть ясный ответ для вас:
Так вот что происходит, начиная с метода верхнего уровня (Button1_Click for UI / MyController.Get для ASP.NET):
- Метод верхнего уровня вызывает GetJsonAsync (в контексте UI / ASP.NET).
- GetJsonAsync запускает REST запрос, вызвав HttpClient.GetStringAsync (все еще в контексте).
- GetStringAsync возвращает незавершенную задачу, указывая, что запрос REST не завершен.
- GetJsonAsync ожидает задачу, возвращенную GetStringAsync. Контекст захвачен и будет использоваться для продолжения использования метода GetJsonAsync позже. GetJsonAsync возвращает незавершенную задачу, указывая, что метод GetJsonAsync не завершен.
- Метод верхнего уровня синхронно блокирует задачу, возвращенную GetJsonAsync. Это блокирует контекстный поток.
- ... В конце концов, запрос REST завершится. Это завершает задачу, которая была возвращена GetStringAsync.
- Продолжение для GetJsonAsync теперь готово к запуску и ожидает, что контекст будет доступен, чтобы он мог выполняться в контексте.
- Тупик. Метод верхнего уровня блокирует поток контекста, ожидая завершения GetJsonAsync, и GetJsonAsync ожидает, что контекст будет бесплатным, чтобы он мог завершить. Для примера пользовательского интерфейса «контекст» представляет собой контекст пользовательского интерфейса; для примера ASP.NET «контекст» представляет собой контекст запроса ASP.NET.
blockquote>Еще одна ссылка, которую вы должны прочитать: