Выбор ответа Middle async/await и Task спрашивают часто обновлено

Дедлок из-за .Result

Вопрос

В обработчике кнопки WinForms вызывают var s = GetAsync().Result;, а внутри GetAsync есть await httpClient.GetStringAsync(url); без ConfigureAwait. Что произойдёт?

Попробуйте сами

Выберите вариант, и откроется разбор.

Показать ответ и разбор

Коротко

Правильный ответ: Дедлок: UI-поток ждёт .Result, а продолжение ждёт UI-поток. await захватил SynchronizationContext UI и хочет продолжить в UI-потоке.

Варианты ответа

  1. Всё сработает, просто UI подвиснет на время HTTP-запроса
  2. .Result бросит InvalidOperationException в UI-потоке
  3. Дедлок: UI-поток ждёт .Result, а продолжение ждёт UI-потокправильный ответ
  4. Продолжение выполнится на пуле потоков, и всё завершится нормально

Разбор

await захватил SynchronizationContext UI и хочет продолжить в UI-потоке. А UI-поток заблокирован на .Result и ждёт завершения задачи, которая не может завершиться без него. Это взаимная блокировка. В ASP.NET Core контекста синхронизации нет, поэтому там такой дедлок не возникает, но блокировка всё равно тратит поток пула. Лечение: асинхронность до конца (await вместо .Result), а в библиотеках ConfigureAwait(false).

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.

Термины по теме