我是异步的新手,并且在尝试让它工作时遇到很多问题:
我正在尝试从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
供消费者使用。
如何让这段代码能够满足我的期望呢?
答案 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
,您需要返回void
,Task
或Task<T>
,这样才能阻止在方法正文中进行任何yield
。
您可以返回IEnumerable<Task<T>>
,返回您之前等待的所有内容,而不是使用await
(您将无法使用async
/ await
方法。)