有人可以解释这里发生的 Parallel.ForEach 循环逻辑吗?
Can someone explain the Parallel.ForEach loop logic happening here?
我只是想学习不同的做事方式 threading/tasks,我想要一种动态更改正在完成的任务的方法,我被指向了 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()" 块是做什么的?我了解 lambda 是什么,但我真的只是不遵循这一点。
我的第二个问题是为什么这是输出?
字数:6 |任务编号:3 | 0
字数:6 |任务编号:3 | 1
字数:6 |任务编号:3 | 2
字数:6 |任务编号:3 | 3
字数:6 |任务编号:3 | 4
字数:6 ----- 已完成。
字数:6 |任务编号:3 | 0
字数:6 |任务编号:3 | 1
字数:6 |任务编号:3 | 2
字数:6 |任务编号:3 | 3
字数:6 |任务编号:3 | 4
字数:6 ----- 已完成。
字数:6 |任务编号:3 | 0
字数:6 |任务编号:3 | 1
字数:6 |任务编号:3 | 2
字数:6 |任务编号:3 | 3
字数:6 |任务编号:3 | 4
字数:6 ----- 已完成。
字数:6 |任务编号:3 | 0
字数:6 |任务编号:3 | 1
字数:6 |任务编号:3 | 2
字数:6 |任务编号:3 | 3
字数:6 |任务编号:3 | 4
字数:6 ----- 已完成。
字数:6 |任务编号:3 | 0
字数:6 |任务编号:3 | 1
字数:6 |任务编号:3 | 2
字数:6 |任务编号:2 | 0
字数:6 |任务编号:2 | 1
字数:6 |任务编号:2 | 2
字数:6 |任务编号:2 | 3
字数:6 |任务编号:2 | 4
字数:6 ----- 已完成。
字数:6 |任务编号:3 | 3
字数:6 |任务编号:3 | 4
字数:6 ----- 已完成。
完成。
拍摄时间:00.00:00:00
为什么每个数字都是 6?我了解线程是如何工作的,但不了解参数的传递/引用。
所以这是我的两个问题。任何帮助都会很棒。我搜索了 google 一段时间,但找不到任何对我有意义的文档。
关于第一个问题:
what does the "action => action()" chunk of the loop do?
这是 actions
列表中每一项的调用。
更正式地说,它被称为 Paraller.ForEach
的主体,它是每次迭代调用一次的委托。更多信息,请查看here.
关于第二个问题:
您应该首先捕获变量 i
,方法是在 for
语句块内使用另一个变量,然后在您创建的 lambda 中使用它,如下所示:
for (int i = 0; i < 6; i++)
{
var j = i;
actions.Add(() => Function1("Word: " + j));
}
您可以找到为什么要这样做的详细解释 here。
public void StartTest()
{
var actions = new List<Action>();
for (int i = 0; i < 6; i++)
{
// you can't pass 'i' directly to the Action here,
// because 'i' is in the scope of where the Action is executed
// and since the parameter of the Action is first evaluated at the
// execution of the Action if you were to put 'i' it checks what value
// 'i' has at the current point in time and since the for-loop finished
// already it is always going to be 6
var word = $"Word: {i}";
actions.Add(() => Function1(word));
}
// you could interpret the lambda 'action => action()' as
// foreach(var action in actions)
// action();
// so it essentially tells you what it's going to do for each
// Action Item in the Action-Collection you passed as Parallel.ForEach's first parameter,
// while 'action' represents the "current" item
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.");
}
我只是想学习不同的做事方式 threading/tasks,我想要一种动态更改正在完成的任务的方法,我被指向了 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()" 块是做什么的?我了解 lambda 是什么,但我真的只是不遵循这一点。
我的第二个问题是为什么这是输出?
字数:6 |任务编号:3 | 0
字数:6 |任务编号:3 | 1
字数:6 |任务编号:3 | 2
字数:6 |任务编号:3 | 3
字数:6 |任务编号:3 | 4
字数:6 ----- 已完成。
字数:6 |任务编号:3 | 0
字数:6 |任务编号:3 | 1
字数:6 |任务编号:3 | 2
字数:6 |任务编号:3 | 3
字数:6 |任务编号:3 | 4
字数:6 ----- 已完成。
字数:6 |任务编号:3 | 0
字数:6 |任务编号:3 | 1
字数:6 |任务编号:3 | 2
字数:6 |任务编号:3 | 3
字数:6 |任务编号:3 | 4
字数:6 ----- 已完成。
字数:6 |任务编号:3 | 0
字数:6 |任务编号:3 | 1
字数:6 |任务编号:3 | 2
字数:6 |任务编号:3 | 3
字数:6 |任务编号:3 | 4
字数:6 ----- 已完成。
字数:6 |任务编号:3 | 0
字数:6 |任务编号:3 | 1
字数:6 |任务编号:3 | 2
字数:6 |任务编号:2 | 0
字数:6 |任务编号:2 | 1
字数:6 |任务编号:2 | 2
字数:6 |任务编号:2 | 3
字数:6 |任务编号:2 | 4
字数:6 ----- 已完成。
字数:6 |任务编号:3 | 3
字数:6 |任务编号:3 | 4
字数:6 ----- 已完成。
完成。
拍摄时间:00.00:00:00
为什么每个数字都是 6?我了解线程是如何工作的,但不了解参数的传递/引用。
所以这是我的两个问题。任何帮助都会很棒。我搜索了 google 一段时间,但找不到任何对我有意义的文档。
关于第一个问题:
what does the "action => action()" chunk of the loop do?
这是 actions
列表中每一项的调用。
更正式地说,它被称为 Paraller.ForEach
的主体,它是每次迭代调用一次的委托。更多信息,请查看here.
关于第二个问题:
您应该首先捕获变量 i
,方法是在 for
语句块内使用另一个变量,然后在您创建的 lambda 中使用它,如下所示:
for (int i = 0; i < 6; i++)
{
var j = i;
actions.Add(() => Function1("Word: " + j));
}
您可以找到为什么要这样做的详细解释 here。
public void StartTest()
{
var actions = new List<Action>();
for (int i = 0; i < 6; i++)
{
// you can't pass 'i' directly to the Action here,
// because 'i' is in the scope of where the Action is executed
// and since the parameter of the Action is first evaluated at the
// execution of the Action if you were to put 'i' it checks what value
// 'i' has at the current point in time and since the for-loop finished
// already it is always going to be 6
var word = $"Word: {i}";
actions.Add(() => Function1(word));
}
// you could interpret the lambda 'action => action()' as
// foreach(var action in actions)
// action();
// so it essentially tells you what it's going to do for each
// Action Item in the Action-Collection you passed as Parallel.ForEach's first parameter,
// while 'action' represents the "current" item
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.");
}