【发布时间】:2018-03-20 16:45:51
【问题描述】:
我目前正在使用 ActionBlock 来处理串行启动的异步作业。它非常适合处理发布到它的每个项目,但无法收集每个作业的结果列表。
我可以使用什么以线程安全的方式收集作业的结果?
我的代码目前是这样的:
var actionBlock = new ActionBlock<int> (async i => await Process(i));
for(int i = 0; i < 100; i++)
{
actionBlock.Post(i);
}
actionBlock.Complete();
await actionBlock.Completion;
我尝试使用 TransformBlock 代替,但在等待完成时它会无限期挂起。完成的状态是“WaitingForActivation”。
我的 TransformBlock 代码是这样的:
var transformBlock = new TransformBlock<int, string> (async i => await Process(i));
for(int i = 0; i < 100; i++)
{
actionBlock.Post(i);
}
actionBlock.Complete();
await actionBlock.Completion;
transformBlock.TryReceiveAll(out IList<string> strings);
【问题讨论】:
-
您的
TransformBlock根本无法卸载它的输出缓冲区,所以它会挂起。一个简单的解决方案是让您的ActionBlock像ConcurrentBag一样将项目添加到并发集合中。 -
谢谢,这几乎就是我最终得到的结果,但我先闲逛了一下,所以我使用了 Parallel.Foreach,这使得代码更加简洁。
-
要将
TransformBlock的所有结果收集为Task<List<T>>,您可以使用ToListAsync找到的方法here。
标签: c# asynchronous task-parallel-library tpl-dataflow