C# 有人能解释一下这里发生的Parallel.ForEach循环逻辑吗?

C# 有人能解释一下这里发生的Parallel.ForEach循环逻辑吗?,c#,multithreading,parallel.foreach,C#,Multithreading,Parallel.foreach,我只是想学习执行线程/任务的不同方法,我想要一种动态更改正在执行的任务的方法,我被指向Parallel.ForEach循环。我做了一个小示例程序,我有几个问题 public void StartTest() { List<Action> actions = new List<Action>(); for (int i = 0; i < 6; i++) { actions.Add(() => Function1(

我只是想学习执行线程/任务的不同方法,我想要一种动态更改正在执行的任务的方法,我被指向Parallel.ForEach循环。我做了一个小示例程序,我有几个问题

public void StartTest()
{
    List<Action> actions = new List<Action>();
    for (int i = 0; i < 6; i++)     
    {
        actions.Add(() => Function1("Word: " + i));
    }
    Parallel.ForEach(actions, new ParallelOptions
    {
        MaxDegreeOfParallelism = 2
    }, action => action());

    Console.WriteLine("Finished. \nTime Taken: " + total.ToString(@"dd\.hh\:mm\:ss"));
    Console.Read();
}


private void Function1(string word)
{
    for (int i = 0; i < 5; i++)
    {
        Console.WriteLine(word + " |  Task Id: " + Task.CurrentId + " |   " + i);
    }
    Console.WriteLine(word + " ----- Completed.");
}
所以我的第一个问题是循环的action=>action块做什么?我理解兰姆达斯是什么,但我真的不明白这一点

我的第二个问题是为什么这是输出

Word:6 |任务Id:3 | 0

Word:6 |任务Id:3 | 1

Word:6 |任务Id:3 | 2

Word:6 |任务Id:3 | 3

Word:6 |任务Id:3 | 4

字:6---完成

Word:6 |任务Id:3 | 0

Word:6 |任务Id:3 | 1

Word:6 |任务Id:3 | 2

Word:6 |任务Id:3 | 3

Word:6 |任务Id:3 | 4

字:6---完成

Word:6 |任务Id:3 | 0

Word:6 |任务Id:3 | 1

Word:6 |任务Id:3 | 2

Word:6 |任务Id:3 | 3

Word:6 |任务Id:3 | 4

字:6---完成

Word:6 |任务Id:3 | 0

Word:6 |任务Id:3 | 1

Word:6 |任务Id:3 | 2

Word:6 |任务Id:3 | 3

Word:6 |任务Id:3 | 4

字:6---完成

Word:6 |任务Id:3 | 0

Word:6 |任务Id:3 | 1

Word:6 |任务Id:3 | 2

Word:6 |任务Id:2 | 0

Word:6 |任务Id:2 | 1

Word:6 |任务Id:2 | 2

Word:6 |任务Id:2 | 3

Word:6 |任务Id:2 | 4

字:6---完成

Word:6 |任务Id:3 | 3

Word:6 |任务Id:3 | 4

字:6---完成

完成了

所用时间:00.00:00:00

为什么每个数字都是6?我了解线程是如何工作的,但不了解参数的传递/引用


这就是我的两个问题。任何帮助都会很棒。我在谷歌搜索了一段时间,没有找到任何对我有意义的文档

关于第一个问题:

循环的action=>action块做什么

这是将为操作列表中的每个项调用的内容

更正式地说,它被称为Paraller.ForEach的主体,每次迭代调用一次委托。有关更多信息,请查看

关于第二个问题:

在创建的lambda中使用变量i之前,应首先通过使用for语句块中的另一个变量捕获变量i,如下所示:

for (int i = 0; i < 6; i++)     
{
    var j = i; 
    actions.Add(() => Function1("Word: " + j));
}

您可以找到一个详细的解释,说明您为什么要这样做。

关于第一个问题:

循环的action=>action块做什么

这是将为操作列表中的每个项调用的内容

更正式地说,它被称为Paraller.ForEach的主体,每次迭代调用一次委托。有关更多信息,请查看

关于第二个问题:

在创建的lambda中使用变量i之前,应首先通过使用for语句块中的另一个变量捕获变量i,如下所示:

for (int i = 0; i < 6; i++)     
{
    var j = i; 
    actions.Add(() => Function1("Word: " + j));
}

您可以找到一个详细的解释,说明为什么要这样做。

您可以通过添加var x=i来修复数字的输出;将函数调用改为使用Word:+x作为参数,这是一个闭包问题。我认为您遇到了一个类似于此处的问题:关键是:您的lamba引用了一个范围在函数本身之外的变量。您的lamba在调用之前不会被解释,一旦被解释,它将获得变量在执行时的值。我是如何变为6的,当然,在该循环中,它应该只有0,1,2,3,4,5?:N0ug4t Link非常清楚地解释了这个问题well@Scriven我最终总是6岁,然后循环退出。@KlausGütter啊,我想我明白了。所有操作都在action=>action;处执行;。在这一点上,我已经变为6,您可以通过添加var x=i来修复数字的输出;将函数调用改为使用Word:+x作为参数,这是一个闭包问题。我认为您遇到了一个类似于此处的问题:关键是:您的lamba引用了一个范围在函数本身之外的变量。您的lamba在调用之前不会被解释,一旦被解释,它将获得变量在执行时的值。我是如何变为6的,当然,在该循环中,它应该只有0,1,2,3,4,5?:N0ug4t Link非常清楚地解释了这个问题well@Scriven我最终总是6岁,然后循环退出。@KlausGütter啊,我想我明白了。所有操作都在action=>action;处执行;。在这一点上,我已经为你解释了6T的问题!感谢您解释此问题的闭包方面 感谢您的解释!