views:

102

answers:

3

i have this code:

    Thread[] threadsArray = new Thread[4];
        for (int i = 0; i < 4; i++)
        {
            threadsArray[i] = new Thread(() => c1.k(i));
        }
        for (int i = 0; i < 4; i++)
        {
            threadsArray[i].Start();
        }
        for (int i = 0; i < 4; i++)
        {
            threadsArray[i].Join();
        }

the function k is this:

void k(int i)
{
    while(true)
      Console.WriteLine(i);
}

for some reason just the last thread is running and printing 4444444.... why aren't all the threads running?

+11  A: 

All of the threads are printing the same variable.

Your lambda expression (() => c1.k(i)) captures the i variable by reference.
Therefore, when the lambda expression runs after i++, it picks up the new value of i.

To fix this, you need to declare a separate variable inside the loop so that each lambda gets its own variable, like this:

    for (int i = 0; i < 4; i++)
    {
        int localNum = i;
        threadsArray[i] = new Thread(() => c1.k(localNum));
    }
SLaks
+1 for this answer. It's basically the same as Winston's, but the explanation is more detailed.
schnaader
On a side note: some languages like F# won't compile if you try to capture a mutable variable in a closure.
gradbot
+3  A: 

You are closing over the i variable.

Try this instead

for (int i = 0; i < 4; i++)
{
    int x = i;
    threadsArray[i] = new Thread(() => c1.k(x));
}
Winston Smith
A: 

What output are you getting? The join in the third loop will ensure each thread is completed before the next one kicks in.

Also it can be an infinite loop. While(true) ....?

Yogendra
No, the third loop blocks the main thread until each background thread completes. The four background threads will still execute in parallel.
Nick Meyer
Why is this down voted? I feel that when a join is called on a thread, It will continue to run till it is finished. During that time, other threads will be waiting. I am also wondering if the function can lead to an infinite loop. Correct me, if i am wrong.
Yogendra
@Yogendra, the part that's incorrect is "During that time, other threads will be waiting." Only one thread (the thread where Join() was called) waits. The others all continue. Yes, you are correct about the infinite loop (in fact, not only *can* it lead to an infinite loop, but it *will* lead to an infinite loop).
Nick Meyer