In the two following snippets, is the first one safe or must you do the second one?
By safe I mean is each thread guaranteed to call the method on the Foo from the same loop iteration in which the thread was created?
Or must you copy the reference to a new variable "local" to each iteration of the loop?
var threads = new List<Thread>();
foreach (Foo f in ListOfFoo)
{
Thread thread = new Thread(() => f.DoSomething());
threads.Add(thread);
thread.Start();
}
-
var threads = new List<Thread>();
foreach (Foo f in ListOfFoo)
{
Foo f2 = f;
Thread thread = new Thread(() => f2.DoSomething());
threads.Add(thread);
thread.Start();
}
Update: As pointed out in Jon Skeet's answer, this doesn't have anything specifically to do with threading.
Edit: this all changes in C# 5, with a change to where the variable is defined (in the eyes of the compiler). From C# 5 onwards, they are the same.
Before C#5
The second is safe; the first isn't.
With
foreach
, the variable is declared outside the loop - i.e.This means that there is only 1
f
in terms of the closure scope, and the threads might very likely get confused - calling the method multiple times on some instances and not at all on others. You can fix this with a second variable declaration inside the loop:This then has a separate
tmp
in each closure scope, so there is no risk of this issue.Here's a simple proof of the problem:
Outputs (at random):
Add a temp variable and it works:
(each number once, but of course the order isn't guaranteed)
In your case, you can avoid the problem without using the copying trick by mapping your
ListOfFoo
to a sequence of threads:Both are safe as of C# version 5 (.NET framework 4.5). See this question for details: Has foreach's use of variables been changed in C# 5?
points to the same reference as
So nothing lost and nothing gained ...
This is an interesting question and it seems like we have seen people answer in all various ways. I was under the impression that the second way would be the only safe way. I whipped a real quick proof:
if you run this you will see option 1 is definetly not safe.
Your need to use option 2, creating a closure around a changing variable will use the value of the variable when the variable is used and not at closure creation time.
The implementation of anonymous methods in C# and its consequences (part 1)
The implementation of anonymous methods in C# and its consequences (part 2)
The implementation of anonymous methods in C# and its consequences (part 3)
Edit: to make it clear, in C# closures are "lexical closures" meaning they don't capture a variable's value but the variable itself. That means that when creating a closure to a changing variable the closure is actually a reference to the variable not a copy of it's value.
Edit2: added links to all blog posts if anyone is interested in reading about compiler internals.