我目前正在使用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);
答案 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))
);
这非常简单,但似乎对性能有好处,并且仍然可以选择限制并行度等。