-1

I have created one function named printInteger() as

static void printInteger(object i)
{
    Console.Write(i + " ");
}

I am creating 10 threads using a for loop and passing integer as an argument via two methods. First Method : passing argument through start()

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

Output in this case is : 1 2 3 5 0 4 6 8 7 9

Second Method : passing argument through Lambda expression

for(int i=0;i<10;i++)
{                          
     new Thread(() =>printInteger(i)).Start();
}

Output in this case is : 2 4 3 4 5 7 8 8 9 10

Behaviour first : As thread will execute in any order, so non increasing order of the Integers is expected.

Behavior second : As i variable refers to the same memory location throughout the loop’s lifetime, so it is also expected that value of i might change during runtime.

My Question is: - Why the result in First Method and the Second Method is different? - We can see both the methods are behaving as a Behavior first. But why only the second method behaving as a Behavior second?

  • It's really unclear to me what you mean by "We can see both the methods are behaving as a Behavior first." – Jon Skeet Oct 27 '17 at 06:43
  • @JonSkeet the output in both methods are in non-increasing order as thread can execute in any order. – mayank bansal Oct 27 '17 at 06:46
  • (The underlying cause for this behaviour has been explained in answers to many different questions, but I *tend* to answer rather than closing as a duplicate as it's a tricky topic to find - the more variations that are available, the more likely it is that other users will find them... and with a direct answer addressing the exact code.) – Jon Skeet Oct 27 '17 at 06:46
  • Ah, I see what you mean. (I skimmed too quickly the first time.) – Jon Skeet Oct 27 '17 at 06:46
  • @JonSkeet Thank you for the quick response. :) – mayank bansal Oct 27 '17 at 06:54
  • @Jon: _"more variations that are available, the more likely it is that other users will find them"_ -- we don't need variations on _answers_ to make duplicates easier to find. "Sign post" duplicate questions, closed as such, work just fine for that. In any case, I fail to see how the answer you posted below is materially different from [the one you wrote](https://stackoverflow.com/a/271447) almost a decade ago. – Peter Duniho Oct 27 '17 at 07:00
  • @PeterDuniho: They can make the answers easier to understand though. In this case, it's specifically about `Thread.Start` evaluating the argument immediately; anyone in the same situation is likely to find this answer more helpful than the ones on duplicates. I don't have strong opinions on this, and for *most* topics I agree with you - variable capture feels slightly different to a lot of topics due to being a bit subtle, I think. – Jon Skeet Oct 27 '17 at 07:37

1 Answers1

3

Why the result in First Method and the Second Method is different?

Because in the first approach you're passing the value of i to the Thread.Start method as its initial state. That is evaluated at the time you call Start.

In the second approach, you're capturing i in your lambda expression. It's evaluated at the point of execution. All your threads will refer to the same variable, and print out the value of the variable at the time they execute.

If you want to use a lambda expression but have each thread capture a different variable, simply introduce a new variable inside the loop:

// I've renamed the method it calls to be more idiomatic
for (int i = 0; i < 10; i++)
{
    // Each iteration creates a separate "copy" variable
    int copy = i;
    new Thread(() => PrintInt32(copy)).Start();
}
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194