Что такое асинхронность в System.Data.Common.DbDataReader.ReadAsync?
Я смотрю на код для DbDataReader (также DbCommand) в справочнике MS и не могу понять, что такое асинхронность в методе ReadAsync().
virtual public Task<bool> ReadAsync(CancellationToken cancellationToken) {
if (cancellationToken.IsCancellationRequested) {
return ADP.CreatedTaskWithCancellation<bool>();
}
else {
try {
return Read() ? ADP.TrueTask : ADP.FalseTask;
}
catch (Exception e) {
return ADP.CreatedTaskWithException<bool>(e);
}
}
}
Метод ReadAsync просто вызывает метод Read и возвращает завершенную задачу. Разве это не блокирует вызывающий поток так же, как и вызов Read напрямую?
Я заметил ту же картину в DbCommand ExecuteReaderAsync и других методах. Они просто вызывают версии синхронизации и возвращают выполненные задачи.
Что мне здесь не хватает?
ОБНОВЛЕНИЕ: я ничего не пропустил, как хорошо объяснил @PeterBons (также в документации). Мне все еще не нравится это, но это моя проблема.
1 ответ
Вы смотрите на виртуальный метод в абстрактном классе. Если вы хотите, чтобы (будущие) реализации могли выполнять действительно асинхронную работу, вам нужно определить сигнатуру метода, которая это позволяет. Так что должно вернуть Task
или же Task<T>
, Помните, что простое использование Задачи не делает ничего асинхронным, оно делает его ожидаемым.
Использование Task<bool>
Тип возвращаемого значения в этом примере виртуальный метод предназначен для облегчения других классов, производных от DbDataReader, для обеспечения реального асинхронного поведения в их реализации ReadAsync.
Например, действительно асинхронная реализация может сделать что-то вроде
class TrueAsyncReader : DbDataReader
{
...
public override async Task<bool> ReadAsync(CancellationToken cancellationToken)
{
...
return await ReadFromDbAsync();
}
}
Как вы можете видеть, теперь у вас могут быть асинхронные и не асинхронные реализации без необходимости изменять сигнатуру метода.
Так как вы можете легко вызвать синхронный код из асинхронного метода, это путь. Вызов асинхронного кода из синхронного метода - дело не из легких.
для не асинхронных реализаций, которые должны вернуть задачу, вы можете вернуть что-то вроде Task.FromResult<T>
или же Task.CompletedTask
, Это не будет блокировать.
Смотрите также ждите Task.CompletedTask для чего?
Подводя итог: реализация по умолчанию не делает ничего асинхронного, но производные классы могут без необходимости изменять сигнатуру метода.