1

I'm having a hard time in understanding the unexpected output for the following program:

class ThreadTest
{
     static void Main()
     {
          for(int i = 0; i < 10; i++)
               new Thread(() => Console.Write(i)).Start();
     }

}

Queries: Different code running in different thread have seperate stacks? If yes, than variables should preserve their values as int is a value type?

LOZ
  • 1,169
  • 2
  • 16
  • 43
mohits00691
  • 137
  • 1
  • 11
  • This has been a problem if you are new to anonymous delegates and you don't know how the code gets generated behind the scenes. I am sure every .net developer should have faced this problem, at least once. – Anand Patel Dec 26 '11 at 04:21

2 Answers2

5

Each thread gets its own stack. The problem that you are facing has nothing to do with stack. The problem is the way it is generating code for your anonymous delegate. Use tool like refelector to understand the code that it is generating. The following will fix your problem:

static void Main() 
        {
            for (int i = 0; i < 10; i++)
            {
                int capture = i;
                new Thread(() => Console.Write(capture)).Start();
            }
        } 

Under the hood

Whenever you use a variable from outer scope (in your case variable i) in anonymous delegate, the compiler generates a new class that wraps anonymous function along with the data that it uses from the outer scope. So in your case the generated class contains - one function and data member to capture the value of variable i. The class definition looks something like:

class SomeClass
{
    public int i { get; set; }

    public void Write()
    {
        Console.WriteLine(i);
    }
}

The compiler re-writes your code as follows:

SomeClass someObj = new SomeClass();
for (int i = 0; i < 10; i++)
{
    someObj.i = i;
    new Thread(someObj.Write).Start();
}

and hence the problem - that you are facing. When you capture a variable, the compiler does the following:

for (int i = 0; i < 10; i++)
{
    SomeClass someObj = new SomeClass();
    someObj.i = i;
    new Thread(someObj.Write).Start();
}

Note the difference in SomeClass instantiation. When you capture a variable, it creates as many instances as there are number of iterations. If you do not capture a variable, it tries to use the same instance for all iterations.

Hope, the above explanation will clarify your doubt.

Thanks

Anand Patel
  • 6,031
  • 11
  • 48
  • 67
2

Yes, threads have their own stacks. But here you also have an issue with variable capture. Try changing the code to:

class ThreadTest
{
    static void Main()
    {
         for(int i = 0; i < 10; i++)
         {
              int j = i;
              new Thread(() => Console.Write(j)).Start();
         }
    }
} 

Notice the change in output? Each thread is being started with a reference to the variable, not the value. When I insert the int j = i; line, we are breaking the variable capture. Your unexpected output has less to do with threading than it does closures.

  • referencing the above code from c#4.o in nutshell, when i tried code above, i don't know for what reason's i am not sure out of every 10 runs i am getting one output like 0213456789 , i will check the code withreflector in the evening as this ustility is not permitted in our workplace. – mohits00691 Dec 26 '11 at 07:07
  • 1
    Threads are not guaranteed to run in any particular order. This is perfectly normal. –  Dec 26 '11 at 09:01