【发布时间】:2020-02-21 22:29:01
【问题描述】:
我从一个非常慢的上游 API 获取项目。我尝试通过使用 TPL 数据流创建多个连接并将它们组合在一起来加快速度,就像这样;
class Stuff
{
int Id { get; }
}
async Task<Stuff> GetStuffById(int id) => throw new NotImplementedException();
async Task<IEnumerable<Stuff>> GetLotsOfStuff(IEnumerable<int> ids)
{
var bagOfStuff = new ConcurrentBag<Stuff>();
var options = new ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism = 5
};
var processor = new ActionBlock<int>(async id =>
{
bagOfStuff.Add(await GetStuffById(id));
}, options);
foreach (int id in ids)
{
processor.Post(id);
}
processor.Complete();
await processor.Completion;
return bagOfStuff.ToArray();
}
问题是我必须等到我查询完Stuff 的整个集合之后才能将它返回给调用者。我更喜欢的是,每当多个并行查询中的任何一个返回一个项目时,我都会以yield return 方式返回该项目。因此我不需要返回sync Task<IEnumerable<Stuff>>,我可以只返回IEnumerable<Stuff>,只要有任何项目返回,调用者就会推进迭代。
我试过这样做;
IEnumerable<Stuff> GetLotsOfStuff(IEnumerable<int> ids)
{
var options = new ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism = 5
};
var processor = new ActionBlock<int>(async id =>
{
yield return await GetStuffById(id);
}, options);
foreach (int id in ids)
{
processor.Post(id);
}
processor.Complete();
processor.Completion.Wait();
yield break;
}
但我得到一个错误
yield 语句不能在匿名方法或 lambda 表达式中使用
如何重组我的代码?
【问题讨论】:
标签: c# enumerate tpl-dataflow