Reputation: 1832
I have been playing around with Threads and Tasks (.net 4) and noticed some odd behavior when you launch multiple threads without waiting a few miliseconds between each thread started call.
The example below when run does not output what I expected:
1
2
1
2
But instead only outputs:
2
2
2
2
Below is the code that I am running.
public static void Main()
{
var items = new[] {"1", "2"};
foreach (var item in items)
{
var thread = new Thread(() => Print(item));
thread.Start();
//var task = Task.Factory.StartNew(() => Print(item));
}
}
static void Print(string something)
{
while (true)
{
Console.WriteLine(something);
Thread.Sleep(1000);
}
}
Now when I call Thread.Sleep(50) after the thread.Start() then only does the output look as expected
1
2
1
2
My question is:
i.e. first thread is launched with parameter of "1", second thread is launched with parameter of "2", however first thread's parameter becomes "2" as well? This makes no sense, especially since Print() method paramter is a value type of string.
Upvotes: 1
Views: 174
Reputation: 50672
Show us the thread starting code and you'll find that you do not pass a constant string but a reference variable and in between calling those Start methods you are probably changing the variable.
Upvotes: 0
Reputation: 3317
The item is evaluated at the time that the thread you create starts due to c# closures. Another way to force the item to evaluate is to introduce a variable so that the closure will include it like so:
foreach (var item in items)
{
var closedItem = item;
var thread = new Thread(() => Print(closedItem));
thread.Start();
}
Upvotes: 2
Reputation: 23551
Your problem is not with threads. Your problem is with the closure and the foreach. You can read here why: http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx
When you play with the timing of the threads you reorder the timings of the main thread as well so sometimes the loop will be executed before the print method of the new thread runs and sometimes after.
Upvotes: 1
Reputation: 1005
Google "access to modified closure". What's happening is your local variable "item" is getting it's value changed before the Print function is invoked. A solution would be to create a new variable inside the scope of the loop and assign item to it.
Upvotes: 5