异步从datareader返回数据

时间:2015-08-04 21:10:30

标签: c# asynchronous sqldatareader

我是异步的新手,并且在尝试让它工作时遇到很多问题:

我正在尝试从SQL加载一个大的结果集,当我运行下面的代码时,我希望发生这种情况:

public async override IEnumerable<DataResult> Read()
{
    using (SqlConnection objConn = new SqlConnection(Options.GetConnectionString()))
    {
        await objConn.OpenAsync();
        SqlCommand comm = new SqlCommand(Options.SqlText, objConn);
        SqlDataReader reader = await comm.ExecuteReaderAsync();

        while (await reader.ReadAsync())
            yield return new DataResult { Reader = reader };
    }
}

制片人代码:

BlockingCollection<DataResult> DataCollection = new BlockingCollection<DataResult>();

var producer = new Producer<DataResult>(() =>
{
    using (var sequenceEnum = sourceEngine.Read().GetEnumerator())
    {
        while (sequenceEnum.MoveNext())
            return sequenceEnum.Current;
    }
    return null;
}, DataCollection);
producer.Start();

它返回数据,因为它在记录中逐个读取数据给生产者,生产者将这些数据存储到BlockingCollection供消费者使用。

如何让这段代码能够满足我的期望呢?

2 个答案:

答案 0 :(得分:3)

您的Read签名不是异步的:

public override IEnumerable<DataResult> Read();

此方法的任何实现都必须是同步的。因此,您只需使用yield并且根本不使用async / await即可实施。

如果您希望它是异步的,请将Read更改为ReadAsync

public override Task<IEnumerable<DataResult>> ReadAsync();

你可以通过(异步)读入列表,然后返回该列表来实现。

但是,如果您真正想要的是异步序列(处理每个数据),那么您应该使用Rx:

public override IObservable<DataResult> Read();

答案 1 :(得分:0)

您遗憾的是,yield方法无法async。将其标记为async,您需要返回voidTaskTask<T>,这样才能阻止在方法正文中进行任何yield

您可以返回IEnumerable<Task<T>>,返回您之前等待的所有内容,而不是使用await(您将无法使用async / await方法。)