【问题标题】:.NET 4.5 parallel processing and for loop.NET 4.5 并行处理和 for 循环
【发布时间】:2013-01-11 06:45:55
【问题描述】:

我正在尝试创建一个取决于可用处理器数量的任务列表。我有一个 for 循环,它的行为似乎很奇怪。我知道 javascript 中的闭包概念,似乎这里可能会发生类似的事情:

 var tasks = new Task[Environment.ProcessorCount]; 
 for(int x = 0; x < Environment.ProcessorCount; x ++)
 {
      tasks[x] = Task.Run(() => new Segment(SizeOfSegment, x * SizeOfSegment, listOfNumbers).generateNewList());
 }

我发现当我在 for 循环中换行时,变量 x 似乎是正确的,所以它从 0 开始到 3 结束(处理器数量为 4)。但是当我在 Segment 的构造函数中放置断点时,我发现在返回调用堆栈时 x 实际上是 4。

任何帮助将不胜感激。

【问题讨论】:

    标签: c# parallel-processing task-parallel-library


    【解决方案1】:

    您在 lambda 表达式中捕获 x - 但是您有一个 single x 变量,该变量在循环过程中更改值,因此当您的任务实际发生时runs,它可能有不同的值。您需要在循环内创建变量的副本,在每次迭代时创建一个新的“变量实例”。然后你就可以安全地捕获那个变量了:

    for(int x = 0; x < Environment.ProcessorCount; x ++)
    {
        int copy = x;
        tasks[x] = Task.Run(() => new Segment(SizeOfSegment,
                                              copy * SizeOfSegment,
                                              listOfNumbers).generateNewList());
    }
    

    (我还建议您将 generateNewList 重命名为 GenerateNewList 以符合 .NET 命名约定。)

    【讨论】:

    • 谢谢乔恩,我对并行处理很陌生,你会说我刚刚发布的答案很好吗?我刚刚对其进行了测试,它似乎可以工作,只是想知道它是否有任何原因可能不理想?
    • @Justin,注意比 C# 5 foreach 嵌套 lambda 表达式中的迭代变量不再捕获 lambda 表达式 Visual C# Breaking Changes in Visual Studio 2012x。所以你可以用foreach替换你的for循环,但在这种情况下看起来很难看。
    • @AlexanderBalte 感谢您的信息!
    猜你喜欢
    • 1970-01-01
    • 2017-09-06
    • 2015-09-13
    • 1970-01-01
    • 1970-01-01
    • 2016-10-21
    • 2022-01-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多