C#ActionBlock收集结果的等效项

时间:2018-03-20 16:45:52

标签: c# asynchronous task-parallel-library tpl-dataflow

我目前正在使用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,但在等待完成时无限期挂起。完成状态为&#34; WaitingForActivation&#34;。

我使用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);

1 个答案:

答案 0 :(得分:1)

事实证明,ConcurrentBag就是答案

var bag = new ConcurrentBag<string>();
var actionBlock = new ActionBlock<int> (async i => 
   bag.Add(await Process(i))
);
for(int i = 0; i < 100; i++)
{
    actionBlock.Post(i);
}
actionBlock.Complete();
await actionBlock.Completion;

现在'bag'包含了所有结果,可以作为IEnumerable访问。

我实际上最终使用的代码使用了Parallel.ForEach而不是ActionBlock。

Parallel.ForEach
(
    inputData, 
    i => bag.Add(await Process(i))
);

这非常简单,但似乎对性能有好处,并且仍然可以选择限制并行度等。