System.Data.Common.DbDataReader.ReadAsync中的异步是什么?

时间:2017-11-10 19:30:05

标签: c# async-await system.data dbdatareader

我在MS reference查看DbDataReader(也是DbCommand)的代码,无法弄清楚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很好地解释了(也在the documentation)。我仍然不喜欢它,但那是我的问题。

1 个答案:

答案 0 :(得分:4)

您正在查看抽象类中的虚方法。如果您希望(未来)实现能够执行一些真正的异步工作,则必须定义允许该方法签名的方法签名。所以它应该返回TaskTask<T>。请记住,只使用一个任务不会使任何异步,它使它等待。

在此示例虚拟方法中使用Task<bool>返回类型是为了便于从DbDataReader派生的其他类在其ReadAsync实现中提供真正的异步行为。

例如,真正的异步实现可以执行类似

的操作
class TrueAsyncReader : DbDataReader
{
    ...

    public override async Task<bool> ReadAsync(CancellationToken cancellationToken) 
    {
        ...

        return await ReadFromDbAsync();
    }
}

如您所见,您现在可以拥有异步和非异步实现,而无需更改方法签名。

由于您可以轻松地从异步方法调用同步代码,因此这是可行的方法。从同步方法调用异步代码是一件好事。

对于需要返回任务的非异步实现,您可以返回Task.FromResult<T>Task.CompletedTask之类的内容。这不会阻止。

另见await Task.CompletedTask for what?

总结一下:默认实现不会执行任何异步,但派生类可以不必更改方法签名。