【发布时间】:2013-04-28 15:29:28
【问题描述】:
这是一个假设的问题/用例,基于在此特定用例的并行 for 循环中使用(在这种情况下)ConcurrentBag 而不是简单数组的好处。
该场景基于使用通用管道模式来分析从 1 到 total 结果的数字,并根据其中一个管道操作的输出存储 result,而不是为空。
结果列表的实际顺序很重要,因此使用简单的列表(字符串类型)。add 会根据每个线程决定返回结果的时间而产生奇怪的结果。
我有以下工作代码:
public IList<string> Execute(int total)
{
var items = new ConcurrentBag<AnalyzerResult>();
Parallel.ForEach(Iterate(1, (total + 1)), d =>
{
foreach (IOperation<T> operation in operations)
{
var result = operation.Execute(d);
if (result != null)
{
items.Add(new AnalyzerResult(d, result));
break;
}
}
});
return items.OrderBy(o=>o.SortOrder).Select(d => d.Result).ToList();
}
AnalyzerResult 是一个简单的不可变类,并且代码只会将新项目推送到袋子中(因此理论上不会有 items 列表中的某些内容被更改的危险)。
基于此,一个简单的数组是否足够(并且包含更少的代码噪音)?或者使用并发类型会被认为是更好的实践/更高的性能?例如:
public IList<string> Execute(int total)
{
var items = new string[total];
Parallel.ForEach(Iterate(1, (total + 1)), d =>
{
foreach (IOperation<T> operation in operations)
{
var result = operation.Execute(d);
if (result != null)
{
items[(d - 1)] = result;
break;
}
}
});
return items.ToList();
}
注意:这不是并发问题,这两种方法都是合法的,并且可以毫无问题地产生所需的结果。
【问题讨论】:
-
由于您保证(通过使用
d作为索引)没有两个线程将同时访问数组的相同元素,我认为这将是安全的。并发类型的开销可能会使其性能降低。我认为普通数组将是最快的合理实现。 -
+1 这也是我的看法,我确实想知道在这个阶段是否有人会出于某种原因为 ConcurrentBag 辩护。
标签: c# concurrency parallel-processing