TPL数据并行问题

时间:2013-01-16 17:38:40

标签: c# .net-4.0 task-parallel-library

我有一个并行处理数据集的情况,最后我想知道它们中有多少已成功处理。我通过跟踪http://msdn.microsoft.com/en-us/library/dd460703.aspxhttp://reedcopsey.com/2010/01/22/parallelism-in-net-part-4-imperative-data-parallelism-aggregation/

上的示例来获取以下虚拟代码
    public void DoWork2()
    {
        int sum = 0;
        Parallel.For<int>(0, 10,
            () => 0,
            (i, lockState, localState) =>
            {
                DummyEntity entity = DoWork3(i);
                if (entity != null)
                {
                    Console.WriteLine("Processed {0}, sum need to be increased by 1.", i);
                    return 1;
                }
                else
                {
                    Console.WriteLine("Processed {0}, sum need to be increased by 0.", i);
                    return 0;
                }
            },
            localState =>
            {
                lock (syncRoot)
                {
                    Console.WriteLine("Increase sum {0} by {1}", sum, localState);
                    sum += localState;
                }
            }
            );
        Console.WriteLine("Total items {0}", sum);
    }

    private DummyEntity DoWork3(int i)
    {
        if (i % 2 == 0)
        {
            return new DummyEntity();
        }
        else
        {
            return null;
        }
    }

但是每次运行时结果都会改变。我认为代码有些问题。但无法弄清楚原因。

1 个答案:

答案 0 :(得分:2)

您的问题是您在超载中的选择。您已经存储了本地状态信息以最小化全局状态的使用,但您没有使用本地状态。

如果你从你给出的例子中注意到他们在循环体中使用了小计(你称之为localState):

subtotal += nums[j];
return subtotal;

将此与您的代码进行比较(更简洁一点):

if (entity != null)
{
    return 1;
}
else
{
    return 0;
}

没有提及localState,所以你已经有效地抛弃了一些答案。如果您将其更改为:

if (entity != null)
{
    return localState + 1;
}
else
{
    return localState;
}

您将在命令行中找到以下答案(针对此特定问题):

Total items 5

本地状态的这种用法是为了减少对共享状态的访问。

以下是使用0..50作为范围的片段:

Processed 22, sum need to be increased by 1.
Processed 23, sum need to be increased by 0.
Increase sum 0 by 1
Processed 8, sum need to be increased by 1.
Processed 9, sum need to be increased by 0.
Processed 10, sum need to be increased by 1.
Processed 11, sum need to be increased by 0.
Increase sum 1 by 2
Increase sum 3 by 8
Increase sum 11 by 10
Processed 16, sum need to be increased by 1.
Processed 17, sum need to be increased by 0.
Processed 18, sum need to be increased by 1.
Increase sum 21 by 4
Total items 25