Выбор ответа Senior async/await и Task обновлено

TaskCompletionSource и синхронные продолжения

Вопрос

Почему new TaskCompletionSource<T>() часто создают с флагом TaskCreationOptions.RunContinuationsAsynchronously?

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

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

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

Коротко

Правильный ответ: Иначе продолжения могут выполниться синхронно внутри SetResult. По умолчанию SetResult может сразу выполнить продолжения ожидающих прямо в своём стеке вызовов.

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

  1. Без флага задача никогда не завершится после вызова SetResult
  2. Флаг делает SetResult потокобезопасным при вызове из разных потоков
  3. Иначе продолжения могут выполниться синхронно внутри SetResultправильный ответ
  4. Флаг запрещает ожидать задачу дважды и тем защищает от гонок

Разбор

По умолчанию SetResult может сразу выполнить продолжения ожидающих прямо в своём стеке вызовов. Если вызывающий держит lock или это поток ввода-вывода, чужой код неожиданно выполнится внутри, что ведёт к дедлокам и подвисаниям. Флаг заставляет планировать продолжения в пул. Задача завершится и без флага, SetResult и TrySetResult и так безопасны для вызова из разных потоков, а многократное ожидание Task разрешено.

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

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

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