【问题标题】:Parallel.For<int> not working as expectedParallel.For<int> 未按预期工作
【发布时间】:2018-09-02 14:10:20
【问题描述】:

我写了一个简单的 Parallel.For 循环。但是当我运行代码时,我得到随机结果。我预计 var total 为 15 (1+2+3+4+5)。我使用 Interlocked.Add 来防止竞争条件和奇怪的行为。有人可以解释为什么输出是随机的而不是 15 吗?

public class Program
{
    public static void Main(string[] args)
    {
        Console.WriteLine("before Dowork");

        DoWork();
        Console.WriteLine("After Dowork");
        Console.ReadLine();
    }

    public static void DoWork()
    {
        try
        {
            int total = 0;
            var result = Parallel.For<int>(0, 6,
                () => 0,
                (i, status, y) =>
                {
                    return i;
                },
                (x) =>
                {
                    Interlocked.Add(ref total, x);
                });

            if (result.IsCompleted)
                 Console.WriteLine($"total is: {total}");
            else Console.WriteLine("loop not ready yet");
        }
        catch(Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }
}

【问题讨论】:

  • 按预期显示 15
  • 我的电脑上没有...
  • localFinally Action&lt;TLocal&gt;每个任务的本地状态执行最终操作的委托。

标签: c# .net parallel-processing


【解决方案1】:

而不是使用

(i, status, y) =>
{
    return i;
}

你应该使用

(i, status, y) =>
{
    return y + i;
}

Parallel.For 将源序列拆分为多个分区。每个分区中的项目是按顺序处理的,但多个分区可以并行执行。

每个分区都有一个本地状态。本地状态是上述 lambda 函数的返回值,也是作为y 参数传递的。所以返回y + i的原因现在应该很清楚了:你应该将本地状态更新为前一个状态和输入值i之和。


在处理完一个分区的每一项后,本地状态的最终值被传递给最后一个函数,在这里你可以总结所有状态:

(x) =>
{
    Interlocked.Add(ref total, x);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-04
    • 2022-01-24
    • 2015-05-11
    • 2020-05-15
    • 2014-10-31
    • 2018-02-12
    • 2014-01-20
    • 2015-01-13
    相关资源
    最近更新 更多