Closures in C# - initating a thread in a function call with a value type

我怕爱的太早我们不能终老 提交于 2020-01-30 12:27:12

问题


I have this code, which works as I wanted but I don't understand exactly why. Thinking about a stack in C, C++, I'd guess that the p variable will be on the stack on each call, and then erased when the method returns. How does the closure of the thread captures it and more over, captures the correct value every time? The output is what I wanted - files are "_a", "_b", "_c".

public enum enumTest
    {
        a = 1,
        b =2,
        c=3
    }     
 private void Form1_Load(object sender, EventArgs e)
    {

        callme(enumTest.a);
        callme(enumTest.b);
        callme(enumTest.c);
    }

    private void callme(enumTest p)
    {
        Thread t = new Thread(() =>
            {
                Thread.Sleep(2000);
                Guid guid = Guid.NewGuid();
                File.WriteAllText(guid.ToString() + "_" + p.ToString(), "");
            });
        t.Start();
    }

回答1:


Lambdas are just glorified anonymous delegates

  • Rick Strahl (http://www.west-wind.com/weblog/posts/2008/Apr/26/Variable-Scoping-in-Anonymous-Delegates-in-C)

Rick's article describes how the compiler generates a class that handles the enumTest p value and delegate.

Also good info at Where does anonymous function body variables saved ?

Basically the compiler creates a new instance of the "closure class" with local variables that must be passed to lambda. This is why you output is correct.

UPDATE

In the case of:

for (int i=0; i<10; i++) 
{
    var t = new Thread(() => { Console.WriteLine(i); }); 
    t.Start(); 
}

The variable i is shared between the for and the lambda. Each thread is accessing the same i. And since the for loop tends to finsih before any thread runs, all you see is '10'.

See http://msdn.microsoft.com/en-us/library/0yw3tz5k(v=vs.80).aspx




回答2:


It's not about closures, here is no any value capturing.

What happening here is that your p parameter is copied by value into the thread's function. Everytime you pass to a function a new value of p is copied to a function.




回答3:


How does the closure of the thread captures it and more over, captures the correct value every time?

That is compiler magic. Simply because the p parameter is being used by the lambda the compiler treats it differently. p is not placed on the stack but on the heap. That is why it still exists after callme() has terminated.



来源:https://stackoverflow.com/questions/14621993/closures-in-c-sharp-initating-a-thread-in-a-function-call-with-a-value-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!