1

I am trying to learn how to use multithreading in C#. I am working from this tutorial, which explains using lambda expressions to pass arguments. I built a toy program to test this, but am confused by the output.

Here is my code:

using System;
using System.Threading;

namespace MultithreadingApplication
{
   class ThreadCreationProgram
   {
      public static void CallToChildThread(int id)
      {
         Console.WriteLine(string.Format("Child thread {0} starts", id));
      }

      static void Main(string[] args)
      {
        for (int i=0; i<10; i++)
        {
            Console.WriteLine(string.Format("i: {0}", i));
            Thread childThread = new Thread( () => CallToChildThread (i) );
             childThread.Start();
        }
      }
   }
}

And here is the output:

i: 0
i: 1
Child thread 1 starts
i: 2
Child thread 2 starts
i: 3
Child thread 3 starts
i: 4
Child thread 4 starts
Child thread 5 starts
i: 5
i: 6
Child thread 6 starts
i: 7
i: 8
Child thread 7 starts
i: 9
Child thread 9 starts
Child thread 8 starts
Child thread 10 starts

The Child function only prints out the value of the id it is passed. I expected these to range from 0 to 9, but CallToChildThread is instead showing 1 to 10. Can someone please explain why?

Roberto
  • 2,054
  • 4
  • 31
  • 46

1 Answers1

2

I just ran the program and got the following result:

i: 0
i: 1
i: 2
Child thread 2 starts
i: 3
Child thread 2 starts
Child thread 3 starts
i: 4
Child thread 4 starts
Child thread 4 starts
i: 5
i: 6
i: 7
Child thread 7 starts
Child thread 7 starts
i: 8
i: 9
Child thread 9 starts
Child thread 9 starts
Child thread 10 starts

This nicely demonstrates one of the problems of multi-threading: Shared variables. In this line:

Thread childThread = new Thread( () => CallToChildThread (i) );

you would assume that you create a lambda with the current value of i. You don't. You create a lambda with a reference to i, the loop variable. Only when your child thread reaches the beginning of CallToChildThread (which might happen at some later time), the value of i is evaluated and copied to the local variable id.

The fix is easy:

int _i = i;
Thread childThread = new Thread(() => CallToChildThread(_i));

This will yield child threads 0 to 9.

Heinzi
  • 167,459
  • 57
  • 363
  • 519