Какой сценарий рассматривается, когда не ожидается асинхронный метод и немедленная оценка IsCompleted?

#c# #async-await

#c# #async-await

Вопрос:

BackgroundService Класс содержит следующий код:

 public virtual Task StartAsync(CancellationToken cancellationToken)
{
    // Store the task we're executing
    _executingTask = ExecuteAsync(_stoppingCts.Token);

    // If the task is completed then return it, this will bubble cancellation and failure to the caller
    if (_executingTask.IsCompleted)
    {
        return _executingTask;
    }

    // Otherwise it's running
    return Task.CompletedTask;
}
  

Я прочитал https://www.markopapic.com/csharp-under-the-hood-async-await / что заставляет меня предположить, что весь код ExecuteAsync вплоть до его первого (если таковой имеется) await ... выполняется до if (_executingTask.IsCompleted) достижения. Поэтому, если в этой части ExecuteAsync возникает какое-либо исключение или если ExecuteAsync возвращается Task.CompletedTask , это приведет к выполнению return _executingTask; .

Правильно ли я это понимаю?

Комментарии:

1. Примечание: я не удивлюсь, если это дубликат более общего вопроса async / await, но большое количество вопросов async / await по SO не позволяет легко найти информацию, которую я ищу.

Ответ №1:

Итак, если в этой части ExecuteAsync возникает какое-либо исключение или ExecuteAsync возвращает задачу.Завершенная задача, которая приведет к выполнению return _executingTask;

В более общем плане, если ExecuteAsync выполняется синхронно, то StartAsync возвращается задача, возвращенная из ExecuteAsync .

В данном конкретном случае (с фоновыми службами) я полагаю, что он предназначен для обработки таких вещей, как проверки предварительных условий, которые обычно выполняются синхронно в начале асинхронного метода. Итак, если фоновая служба синхронно определяет, что она не может быть запущена, то StartAsync вернет задачу с ошибкой.

Такой код встречается крайне редко, а дизайн сомнителен. Например, если фоновая служба асинхронно определяет, что она не может быть запущена, то уведомления об этом нет. Я думаю, что поведение было бы более последовательным для удаления всего if (_executingTask.IsCompleted) блока или изменения ExecuteAsync абстракции на отдельные InitializeAsync и ExecuteAsync части.