I'm answering the follow-up question:
But i am still wondering that how adding a string tmp
variable and passing that to the function worked.
To get an idea, you should better understand what a closure is:
http://en.wikipedia.org/wiki/Closure_(computer_programming)[
^].
Let's consider all the detail of the call, but simplify and change is it:
void TestThread() {
string stackVariable = "My variable";
t = new Thread(() => Shrink(stackVariable));
t.Start();
stackVariable = "New value";
}
What happens with the variable
stackVariable
? Normally, when you call a method, its local variables are created on stack and are discarded after the call. But how the code above can possible work?
The value of
stackVariable
may be needed even after the call to
TestThread
, because nobody knows when a time slice for the thread starts. So the local variable is not local anymore. There is a special mechanism that suspend removal of local variables. It is kind of "promoted" to a static variable only for the sake of being accessible to a delegate. This effect can only come in play with anonymous methods and has nothing to do with threads. Also, lambda form of the delegate makes no difference; the only essential factor is using anonymous method.
Not try to analyze the absurdism of the situation with loop variable. Normally, the loop variable is designed to be stack-only. You force the lifetime of the variable to be prolonged even beyond the loop block, as it is used by a thread. (By the way, I once found, this is the only way to check what happens with the loop variable when execution goes out to the loop block where it is not accessible "officially").
To simplify the situation, let's make a sample of using of this effect without threads, even without parameters:
void SetupLocalVaribleCount() {
int localCounter = 0;
MyButton.Click += (sender, eventArg) => {
localCounter++;
MyForm.Text = string.Format("Clicked {0} times", localCounter);
}
}
Can you see what's going on? You call
SetupLocalVaribleCount
and return before the user clicks the button. When the click happens, the variable
localCounter
is still used even though the stack frame of
SetupLocalVaribleCount
is gone forever. This code will really work and count clicks using the variable which is "officially" local and would be created on stack and removed if not the anonymous delegate using it.
You should not be afraid of using anonymous methods, with lambda or not, or
closures, for that matter, but you need to understand the subtle consequences of it.
—SA