I'm getting some strange behavior... when I iterate over the dummyText
List
in the ThreadTest
method I get an index out of range exception (ArgumentOutOfRangeException
), but if I remove the threads and I just print out the text, then everything works fine.
This is my main method:
public static Object sync = new Object();
static void Main(string[] args)
{
ThreadTest();
Console.WriteLine("Press any key to continue.");
Console.ReadKey();
}
This method throws the exception:
private static void ThreadTest()
{
Console.WriteLine("Running ThreadTest");
Console.WriteLine("Running ThreadTest");
List<String> dummyText = new List<string>()
{ "One", "Two", "Three", "Four", "Five",
"Six", "Seven", "Eight", "Nine", "Ten"};
for (int i = 0; i < dummyText.Count; i++)
{
Thread t = new Thread(() => PrintThreadName(dummyText[i])); // <-- Index out of range?!?
t.Name = ("Thread " + (i));
t.IsBackground = true;
t.Start();
}
}
private static void PrintThreadName(String text)
{
Random rand = new Random(DateTime.Now.Millisecond);
while (true)
{
lock (sync)
{
Console.WriteLine(Thread.CurrentThread.Name + " running " + text);
Thread.Sleep(1000+rand.Next(0,2000));
}
}
}
This does not throw the exception:
private static void ThreadTest()
{
Console.WriteLine("Running ThreadTest");
List<String> dummyText = new List<string>()
{ "One", "Two", "Three", "Four", "Five",
"Six", "Seven", "Eight", "Nine", "Ten"};
for (int i = 0; i < dummyText.Count; i++)
{
Console.WriteLine(dummyText[i]); // <-- No exception here
}
}
Does anybody know why this is happening?
When you pass a local variable into a thread or
ThreadPool
delegate through a closure, you need to make a copy of the variable. As in:If you don't do this, then the variable basically gets passed in by reference, and the index will exceed the bounds of the array at the very end of the
for
loop (which may happen long before the closure is ever executed).