背后的整个想法
Parallel.ForEach()是,您有一组线程,每个线程处理集合的一部分。正如您所注意到的,这不适用于
async-
await,您想在异步调用期间释放线程。
您可以通过阻塞
ForEach()线程来“修复”该问题,但这使
async- 的全部观点无效
await。
您可以做的是使用TPL Dataflow代替
Parallel.ForEach(),它
Task很好地支持异步。
具体来说,您的代码可以使用a编写
TransformBlock,该代码
Customer使用
asynclambda 将每个id转换为a
。可以将该块配置为并行执行。您可以将该块链接到,
ActionBlock然后将每个块写入
Customer控制台。设置区块网络后,您可以将
Post()每个ID分配到
TransformBlock。
在代码中:
var ids = new List<string> { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" };var getCustomerBlock = new TransformBlock<string, Customer>( async i => { ICustomerRepo repo = new CustomerRepo(); return await repo.GetCustomer(i); }, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded });var writeCustomerBlock = new ActionBlock<Customer>(c => Console.WriteLine(c.ID));getCustomerBlock.linkTo( writeCustomerBlock, new DataflowlinkOptions { PropagateCompletion = true });foreach (var id in ids) getCustomerBlock.Post(id);getCustomerBlock.Complete();writeCustomerBlock.Completion.Wait();尽管您可能希望将的并行性限制
TransformBlock为一些小常数。另外,您可以限制的容量,
TransformBlock并使用异步添加项目
SendAsync(),例如,如果集合太大。
与您的代码(如果可行)相比,另一个好处是,写入将在单个项目完成后立即开始,而不必等到所有处理都完成了。



