Answered by:
Strange behavior with Task.run

Question
-
public static void Main() { Console.WriteLine("Starting."); for (int i = 0; i < 4; ++i) Task.Run(() => Console.WriteLine(i)); Console.WriteLine("Finished. Press <ENTER> to exit."); Console.ReadLine(); }
Can anyone check if it's bug in .net?
Sunday, November 26, 2017 2:54 PM
Answers
-
Hello Animee.Young,
>>Strange behavior with Task.run
The issue is no relating to task.run method. the real course of the phenomenon is "closures".
There is a very professional people given a understanding of "closures".
Quote:In essence, a closure is a block of code which can be executed at a later time, but which maintains the environment in which it was first created - i.e. it can still use the local variables etc of the method which created it, even after that method has finished executing.
And the mistake usually occurs in anonymous methods and lambda expressions. In your case, Because () => Console.WriteLine(k) means "it will write the current value of variable v in console". And when the methods run, clearly the last value that was assigned to k was 4,so it still has that value.
The following is a simple demo for you understanding.
Console.WriteLine("Starting."); var funcs = new List<Action>(); for (int i = 0; i < 4; ++i) funcs.Add(() => Console.WriteLine(i)); for (int j = 0; j < funcs.Count; j++) { funcs[j](); } Console.WriteLine("Finished. Press <ENTER> to exit."); Console.ReadLine();
There is a MSDN blog that you could look up it.
Sincerely,
Fei Hu
MSDN Community Support
Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.- Marked as answer by Aimee.Young Monday, December 4, 2017 2:58 PM
Monday, November 27, 2017 8:09 AM -
Try this:
for( int i = 0; i < 4; ++i )
{
var k = i;
Task.Run( () => Console.WriteLine( k ) );
}
There is a single variable i, which is shared between tasks.
- Proposed as answer by madmir Sunday, November 26, 2017 4:35 PM
- Marked as answer by Aimee.Young Monday, December 4, 2017 2:58 PM
Sunday, November 26, 2017 4:34 PM -
Can anyone check if it's bug in .net?
- Proposed as answer by Charles He21Microsoft employee Monday, December 4, 2017 8:39 AM
- Marked as answer by Aimee.Young Monday, December 4, 2017 2:58 PM
Sunday, November 26, 2017 7:03 PM
All replies
-
Try this:
for( int i = 0; i < 4; ++i )
{
var k = i;
Task.Run( () => Console.WriteLine( k ) );
}
There is a single variable i, which is shared between tasks.
- Proposed as answer by madmir Sunday, November 26, 2017 4:35 PM
- Marked as answer by Aimee.Young Monday, December 4, 2017 2:58 PM
Sunday, November 26, 2017 4:34 PM -
Can anyone check if it's bug in .net?
- Proposed as answer by Charles He21Microsoft employee Monday, December 4, 2017 8:39 AM
- Marked as answer by Aimee.Young Monday, December 4, 2017 2:58 PM
Sunday, November 26, 2017 7:03 PM -
Hello Animee.Young,
>>Strange behavior with Task.run
The issue is no relating to task.run method. the real course of the phenomenon is "closures".
There is a very professional people given a understanding of "closures".
Quote:In essence, a closure is a block of code which can be executed at a later time, but which maintains the environment in which it was first created - i.e. it can still use the local variables etc of the method which created it, even after that method has finished executing.
And the mistake usually occurs in anonymous methods and lambda expressions. In your case, Because () => Console.WriteLine(k) means "it will write the current value of variable v in console". And when the methods run, clearly the last value that was assigned to k was 4,so it still has that value.
The following is a simple demo for you understanding.
Console.WriteLine("Starting."); var funcs = new List<Action>(); for (int i = 0; i < 4; ++i) funcs.Add(() => Console.WriteLine(i)); for (int j = 0; j < funcs.Count; j++) { funcs[j](); } Console.WriteLine("Finished. Press <ENTER> to exit."); Console.ReadLine();
There is a MSDN blog that you could look up it.
Sincerely,
Fei Hu
MSDN Community Support
Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.- Marked as answer by Aimee.Young Monday, December 4, 2017 2:58 PM
Monday, November 27, 2017 8:09 AM