4

这是向 IDbCommand 接口添加异步功能的合理方法吗?

public async static Task<IDataReader> ExecuteReaderAsync(this IDbCommand self) {
    DbCommand dbCommand = self as DbCommand;
    if (dbCommand != null) {
        return await dbCommand.ExecuteReaderAsync().ContinueWith(task => (IDataReader)task.Result);
    } else {
        return await Task.Run(() => self.ExecuteReader());
    }
}

具体来说,我不完全确定使用“ContinueWith”来伪造“Task”的协方差的效果。

此外,在传入的“self”实例不从 DbCommand 继承的不太可能的情况下,在执行“self.ExecuteReader()”期间是否会消耗和阻塞线程池线程?

这是我完整实现异步支持的 IDb 扩展的链接。

谢谢

4

2 回答 2

4

仅仅因为它更干净,我会利用您正在使用的事实asyncawait取消ContinueWith(). 在 a 上使用时await计算为类型的对象。我打算建议语法,但后来我记得编译器已经知道了。在 VS 2013 和 VS 2015 Preview 中进行了测试(不确定您的目标是什么,但我认为所有支持的 C# 编译器都应该适用于此):TResultTask<TResult>return (IDataReader)await dbCommand.ExecuteReaderAsync();DbDataReaderIDataReaderawait

public async static Task<IDataReader> ExecuteReaderAsync(this IDbCommand self) {
    DbCommand dbCommand = self as DbCommand;
    if (dbCommand != null) {
        return await dbCommand.ExecuteReaderAsync();
    } else {
        return await Task.Run(() => self.ExecuteReader());
    }
}

现在您正在await充分利用它的潜力并节省几个字节的代码;-)。

当然,这个实现最大的问题是self as DbCommand. 在我看来,DbCommand应该用IDbCommand. 这将允许您删除运行时强制转换。但是,如果在将所有内容IDbCommandDbCommand

Visual Studio 2017 语法

使用较新版本的 C#,您可以使用is关键字而不是as编写更简洁的代码:

public async static Task<IDataReader> ExecuteReaderAsync(this IDbCommand self) {
    if (self is DbCommand dbCommand) {
        return await dbCommand.ExecuteReaderAsync();
    } else {
        return await Task.Run(() => self.ExecuteReader());
    }
}
于 2014-12-30T16:00:52.237 回答
3

如果您使用的是 .NET 4.5 ,您将错过asyncand 。await您尝试的方式是正确的,并希望您分别处理连接。

public static async Task<IDataReader> ExecuteReaderAsync(this IDbCommand self)
{
    var dbCommand = self as DbCommand;
    if (dbCommand != null)
    {
        return await dbCommand.ExecuteReaderAsync();
    }

    return await Task.Run(() => self.ExecuteReader());
}
于 2014-10-01T20:52:06.637 回答