0

我有这段代码,它可以按我的意愿工作,但我不明白为什么。考虑 C、C++ 中的堆栈,我猜 p 变量将在每次调用时位于堆栈上,然后在方法返回时被擦除。线程的闭包如何捕获它,并且每次都捕获正确的值?输出是我想要的——文件是“_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();
    }
4

3 回答 3

1

这与闭包无关,这里没有任何价值捕获。

这里发生的是您的p参数按值复制到线程的函数中。每次传递给函数时,都会将新p 复制到函数中。

于 2013-01-31T09:12:36.040 回答
1

Lambda 只是美化的匿名代表

Rick 的文章描述了编译器如何生成一个类来处理enumTest p值和delegate.

匿名函数体变量保存在哪里也有很好的信息?

基本上,编译器使用必须传递给 lambda 的局部变量创建“闭包类”的新实例。这就是您输出正确的原因。

更新

如果是:

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

变量在和i之间共享。每个线程都在访问相同的. 而且由于 for 循环往往在任何线程运行之前结束,所以你看到的只是“10”。forlambdai

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

于 2013-01-31T09:26:11.413 回答
1

线程的闭包如何捕获它,并且每次都捕获正确的值?

这就是编译器的魔力。仅仅因为p参数被 lambda 使用,编译器会以不同的方式对待它。 p不是放在栈上,而是放在堆上这就是为什么它在callme()终止后仍然存在的原因。

于 2013-01-31T09:27:42.787 回答