5

I am learning to use the Task Parallel Library(TPL) in C#, and wrote the following code (you can copy-past it and run it).

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace parallelTaskLibrary
{
    class Program
    {
        static void Main(string[] args)
        {
            for (int i = 0; i < 6; i++)
            {
                var t01 = Task.Factory.StartNew(() => Console.WriteLine("in loop: i = {0}", i));
            }

            Console.WriteLine("press any key to terminate...");
            Console.ReadKey();
        }      
    }
}

in the for loop, the counter index i cannot start an iteration with a value of i = 6. However, the output i got is this:

press any key to terminate...
in loop: i = 6
in loop: i = 6
in loop: i = 6
in loop: i = 6
in loop: i = 6
in loop: i = 6

However, in another launch(didn't change in the code), i got this:

in loop: i = 1
in loop: i = 1
in loop: i = 2
in loop: i = 3
in loop: i = 4
in loop: i = 5
press any key to terminate...

which is plausible...

I Debugged the code, and found that i value is: 0,1,3,4,5,6

How did that happen?

Why i got (i = 6) in the loop?

is there anything wrong in my code?

Note: I'm using visual studio 2010

0

5 Answers 5

18

because there is a closure problem. you need to copy the variable i in temporary variable.

for (int i = 0; i < 6; i++)
{
    var tempi = i;
    var t01 = Task.Factory.StartNew(() => Console.WriteLine("in loop: i = {0}", tempi));
}

Because your task starts in another thread. but you dont wait for that task in current thread. so the program will comeback and will increment the counter. since the delegate you have created uses the original counter then it prints 6. because counting to 6 is done much faster than creating a new task.

When you use debugger the new task will get a chance to print the value before you continue to increment the counter,

3

With that code you have a working sample about what you have to be aware when you are programming multi-threaded-applications. The problem is that starting a thead takes some time and in this time the main-thread finishes iterating through the for-loop. At the time the main-thread has finished i == 6 and each thread accesses the value of i which is 6. A solution is to make a local variable and copy the value of i

for(...)
{
    int temp = i;
    var t1 //.....
}
2

Obviously, you will print the value of "i" as it is when your code (the delegate with the Console.WriteLine statement) is executed, which may very well be at a slightly later time.

This is probaby what you want:

for (int i = 0; i < 6; i++)
{
  var j = i;
  var t01 = Task.Factory.StartNew(() => Console.WriteLine("in loop: i = {0}", j));
}

>is there anything wrong in my code?

Yes :-)

2
for (int i = 0; i < 6; i++)

Starting from C# 2012 following code will work as you expect:

foreach (int i in Enumerable.Range(0, 6))

http://ideone.com/naaZNx - example.

Declaring variable inside of the loop was one of the breaking changes in VS2012.

3
  • @HansKesting, I know about the problem. And foreach will declare variable inside. Read about breaking changes of VS2012 please.
    – Qwertiy
    Dec 17, 2015 at 7:48
  • You are right, I forgot about that. You may want to add the expalantion to your answer. Dec 17, 2015 at 7:52
  • you're right, that worked indeed, however, i was looking for the reason at the OS level of what was happening. Dec 17, 2015 at 9:49
0

Why i got (i = 6) in the loop?

All the steps :

i=0
i<6 => create Thread1
i++ => i=1
i<6 => create Thread2
i++ => i=2
i<6 => create Thread3
i++ => i=3
i<6 => create Thread4
i++ => i=4
i<6 => create Thread5
i++ => i=5
i<6 => create Thread6
i++ => i=6
i<6 NO => leave for

The main thread executes :

Console.WriteLine("press any key to terminate...");

All 6 Threads created execute : Console.WriteLine("in loop: i = {0}", i) where i=6

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.