IDbCommand缺少ExecuteReaderAsync

Kev*_*don 7 c# asynchronous async-await .net-core-2.0

我正在使用.NET Core 2.0.我有以下调用函数IDbCommand.ExecuteReader

public async Task<IEnumerable<Widget>> ReadAllAsync(
    System.Data.IDbConnection databaseConnection,
    System.Data.IDbTransaction databaseTransaction)
{
    var commandText = "SELECT WidgetId, Name FROM Widget";

    // _databaseCommandFactory.Create returns an IDbCommand
    var command = this._databaseCommandFactory.Create(databaseConnection, databaseTransaction, commandText);

    using (var dataReader = command.ExecuteReader())
    {
        // iterate through the data reader converting a collection of Widgets (`IEnumerable<Widget>`)
    }
}
Run Code Online (Sandbox Code Playgroud)

我收到警告

这种异步方法缺少"等待"运算符并将同步运行.考虑使用'await'运算符等待非阻塞API调用,或'await Task.Run(...)'在后台线程上执行CPU绑定工作.

我正考虑将command.ExecuteReader()声明转换await Task.Run(() => command.ExecuteReader())为警告中的建议.但我不确定这是正确的方法,我相信Task.Run(...)是基于CPU的工作.这主要是IO工作.

所以我的问题是

  1. Task.Run(...)正确的方法吗?
  2. 如果没有,还有其他解决方案吗?
  3. 或者我应该暂时忽略警告并等待直到ExecuteReaderAsync添加到IDbCommand界面?(有计划吗?)

Yve*_*omb 7

await关键字是允许的方法来异步运行.该async关键字,可以使用的await方法中的关键字,并在管理回报次助攻.

直到await被调用方法才会同步运行.

所以这一切都是同步运行的.在完成之前,它不会返回任何内容或移动方法.

public async Task<IEnumerable<Widget>> ReadAllAsync(
    System.Data.IDbConnection databaseConnection,
    System.Data.IDbTransaction databaseTransaction)
{
    var commandText = "SELECT WidgetId, Name FROM Widget";

    // _databaseCommandFactory.Create returns an IDbCommand
    var command = this._databaseCommandFactory.Create(databaseConnection, databaseTransaction, commandText);

    using (var dataReader = command.ExecuteReader())
    {
        // iterate through the data reader converting a collection of Widgets (`IEnumerable<Widget>`)
    }
}
Run Code Online (Sandbox Code Playgroud)

通过转换到DbCommand大多数IDbCommand派生实现已经执行的操作,然后转换到DbCommand并添加await将工作,例如

var dbCommand = (DbCommand) command;
using (var dataReader = await dbCommand.ExecuteReaderAsync())
{
    while (await dataReader.ReadAsync()) 
    {
        // iterate through the data reader converting a collection of Widgets (`IEnumerable<Widget>`)
    }
}
Run Code Online (Sandbox Code Playgroud)

或创建一个单独的任务

public async Task MyAsyncMethod()
{
  // Do your stuff that takes a long time
}

public async Task CallMyAsyncMethod()
{
  // We can await Tasks, regardless of where they come from.
  await MyAsyncMethod();

}
Run Code Online (Sandbox Code Playgroud)

这样 - 程序将在等待从此方法返回时继续,而不是锁定UI和所有其他内容.

  • 谢谢@YvetteColomb.我现在决定向DbCommand投票.我不完全确定如何创建单独的任务会有所帮助.这不仅仅是将问题转移到另一种方法而且我仍然得到所有的警告吗? (2认同)
  • 看起来像投射到DbCommand引起了一些问题.我得到一个"已经有一个与此命令关联的开放DataReader,必须先关闭它." 我尝试第二次获取数据时刷新异常(刷新页面).我的连接和事务都包含在使用中,因此不确定是否发生了什么. (2认同)
  • @KevinBrydon也尝试包装命令.还看看这个答案重新上一次错误/sf/answers/1479211751/ (2认同)
  • @YvetteColomb误报.我的代码有问题.有一个应该返回任务但返回void的方法.在该方法内部是对我的一个异步存储库的调用.学过的知识! (2认同)