3

This is a hypothetical question/use-case based on the benefits of using (in this case) a ConcurrentBag over a simple array from within a Parallel for loop for this particular use-case.

The scenario is based on using a common Pipeline pattern to analyse numbers from 1 to total results, storing the result based on the output from one of the Pipeline operations not being null.

The actual order of the resultant list is important, thus using a simple list(of type string).add would result in oddness based on when each thread decides to return a result.

I have the following working code:

    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 is a simple immutable class, and the code only ever pushes new items to the bag (so no danger of something in the items list being changed, in theory).

Based on this, would a simple Array be sufficient (and contain less code noise)? or would the use of a concurrent type be considered better practice/more performant? For example:

    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();
    }

Note: This is not a concurrency issue, both methods are legal and produce the desired result without issue.

4

1 回答 1

2

我最初选择了“您需要并发保护”的答案,但随后重新阅读了您问题的第二部分。

这看起来应该可以工作,因为您不会尝试从两个不同的线程写入内存中的同一位置。因此,消除锁和线程亲和性(ConcurrentBag给出的)应该会显着提高性能。

真正的问题是 - 它增加了多少,是否需要增加(需要分析),您将来是否会更改此设置,以便您需要并发保护。

照原样,它应该没问题,而且可读性很强。你可能想评论这段代码为什么你这样做,以确保有人不会随便浏览它并认为“并发问题”(就像我刚刚做的那样)并“修复”它。

于 2013-04-28T15:48:24.727 回答