【问题标题】:What is async in System.Data.Common.DbDataReader.ReadAsync?System.Data.Common.DbDataReader.ReadAsync 中的异步是什么?
【发布时间】:2018-04-24 02:28:48
【问题描述】:

我正在查看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 中)。我仍然不喜欢它,但这是我的问题。

【问题讨论】:

  • 几个提供者(包括流行的)不支持与他们的数据库真正的异步通信,所以他们只是继承了这个实现。那些这样做的人 - 覆盖并提供真正的实施。是的,这些方法可以被抽象化,但另一个设计决定是不强制不支持这些方法的提供者提供他们自己的虚假实现。

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


【解决方案1】:

您正在查看抽象类中的虚拟方法。如果您希望(未来)实现能够做一些真正的异步工作,您将必须定义一个允许这样做的方法签名。所以它应该返回一个TaskTask&lt;T&gt;。请记住,仅使用 Task 不会使任何事情异步,而是使其可等待。

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

例如,真正的异步实现可以做类似的事情

class TrueAsyncReader : DbDataReader
{
    ...

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

        return await ReadFromDbAsync();
    }
}

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

因为您可以轻松地从异步方法调用同步代码,所以这是要走的路。从同步方法调用异步代码是不可能的。

对于需要返回任务的非异步实现,您可以返回类似Task.FromResult&lt;T&gt;Task.CompletedTask 的内容。这不会阻塞。

另见await Task.CompletedTask for what?

总结一下:默认实现不做任何异步操作,但派生类可以无需更改方法签名。

【讨论】:

  • 类是抽象的,但方法不是。您可以将您的实际对象转换为 DbDataReader 并调用此方法。我的问题是它给了我什么,它真的是异步的吗?
  • @gajo357 该方法是虚拟的,因此可以在实现中被覆盖。默认实现不是异步的,任何覆盖方法都可以是异步的。您在问题中显示的代码是同步运行的,其中没有任何异步运行。请记住,仅使用 Task 不会使任何内容异步。
  • 异步方法和可等待方法之间存在很大差异。我觉得这里值得编辑。
  • @Peter Bons 谢谢。我不确定我是否错过或误解了什么。我仍然不知道为什么它在那里。它有一个虚假的实现,它不在 IDbDataReader 接口中。看起来很误导人。
  • @gajo357 它有助于其他从 DbDataReader 派生的类在 ReadAsync 的实现中提供真正的异步行为。
猜你喜欢
  • 2017-09-03
  • 1970-01-01
  • 1970-01-01
  • 2018-11-16
  • 2011-05-09
  • 2013-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多