I am just trying to learn the different ways of doing threading/tasks and I wanted a way to dynamically change the tasks that were being done and I was pointed to the Parallel.ForEach loop. I made a little example program and I have a few questions.
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.");
}
So my first question is what does the "action => action()" chunk of the loop do? I understand what lambdas are but I really am just not following this.
My second question is why is this the output?
Word: 6 | Task Id: 3 | 0
Word: 6 | Task Id: 3 | 1
Word: 6 | Task Id: 3 | 2
Word: 6 | Task Id: 3 | 3
Word: 6 | Task Id: 3 | 4
Word: 6 ----- Completed.
Word: 6 | Task Id: 3 | 0
Word: 6 | Task Id: 3 | 1
Word: 6 | Task Id: 3 | 2
Word: 6 | Task Id: 3 | 3
Word: 6 | Task Id: 3 | 4
Word: 6 ----- Completed.
Word: 6 | Task Id: 3 | 0
Word: 6 | Task Id: 3 | 1
Word: 6 | Task Id: 3 | 2
Word: 6 | Task Id: 3 | 3
Word: 6 | Task Id: 3 | 4
Word: 6 ----- Completed.
Word: 6 | Task Id: 3 | 0
Word: 6 | Task Id: 3 | 1
Word: 6 | Task Id: 3 | 2
Word: 6 | Task Id: 3 | 3
Word: 6 | Task Id: 3 | 4
Word: 6 ----- Completed.
Word: 6 | Task Id: 3 | 0
Word: 6 | Task Id: 3 | 1
Word: 6 | Task Id: 3 | 2
Word: 6 | Task Id: 2 | 0
Word: 6 | Task Id: 2 | 1
Word: 6 | Task Id: 2 | 2
Word: 6 | Task Id: 2 | 3
Word: 6 | Task Id: 2 | 4
Word: 6 ----- Completed.
Word: 6 | Task Id: 3 | 3
Word: 6 | Task Id: 3 | 4
Word: 6 ----- Completed.
Finished.
Time Taken: 00.00:00:00
Why is every single number 6? I understand how the threading is working, but not the passing / referencing of the parameters.
So those are my two questions. Any help would be fantastic. I searched google for a while and could not find any documentation that made sense to me.
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.");
}