Regarding local variable passing in Thread

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


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.