4

I am relatively green to proper threading, I have this, it's modified for simplicity but it is essentially the same thing:

//Global:
N=2
bool[] mySwitches;

//In my main:

mySwitches = new bool[N];
for (int i = 0; i < N; i++)
{
    ThreadList.Add(new Thread(() => Worker(i)));
    ThreadList[i].Start();
}

//Outside of main:

Private Void Worker(int num)
{
  while(true)
  {
    if (mySwitches[num]) //error happes here because num is equal to N, how?
    {
        //do something
    }
  }
}

As shown above, somehow a worker thread gets a value of num=N, I expect it to only reach N-1. I know that i will get incremented after the Worker is created, is i somehow getting passed by reference instead of value?

I tried to fix the issue by putting a test before my while loop to return if num=N, but even with this provision I get the same error. This leads me to believe that num is incremented somehow after the thread starts.

I fixed this issue by putting a Sleep(20) directly after ThreadList[i].Start(), but I don't really like using Sleep, and it's clear I don't know how this threading scenario actually works.

Can anyone shed any light on this?

Gorchestopher H
  • 1,141
  • 3
  • 17
  • 35

1 Answers1

5

i is captured by its reference. Change your code as

for (int i = 0; i < N; i++)
{
    var thInx = i;
    ThreadList.Add(new Thread(() => Worker(thInx)));
    ThreadList[thInx].Start();
}

For more info: http://csharpindepth.com/articles/chapter5/closures.aspx

EZI
  • 15,209
  • 2
  • 27
  • 33
  • 2
    I got caught by this one once, but like you, soon as I made a local copy, it all sorted. I think this is an easy one to fall for – BugFinder Aug 18 '15 at 13:40
  • So it doesn't have so much to do with the type of variable used, just the fact that the compiler will use the same variable till you make a new local one. Awesome, thanks! – Gorchestopher H Aug 18 '15 at 14:00
  • Its the most common closure issue, have been caught out once in the past and learned the 'hard lesson' :) – sppc42 Aug 18 '15 at 14:20