关于Thread中传递的局部变量 [英] Regarding local variable passing in Thread

查看:29
本文介绍了关于Thread中传递的局部变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很难理解以下程序的意外输出:

I'm having a hard time in understanding the unexpected output for the following program:

class ThreadTest
{
     static void Main()
     {
          for(int i = 0; i < 10; i++)
               new Thread(() => Console.Write(i)).Start();
     }

}

查询:在不同线程中运行的不同代码有不同的堆栈?如果是,那么变量应该保留它们的值,因为 int 是值类型?

Queries: Different code running in different thread have seperate stacks? If yes, than variables should preserve their values as int is a value type?

推荐答案

每个线程都有自己的堆栈.您面临的问题与堆栈无关.问题在于它为匿名委托生成代码的方式.使用 reflector 之类的工具来理解它生成的代码.以下内容将解决您的问题:

Each thread gets its own stack. The problem that you are facing has nothing to do with stack. The problem is the way it is generating code for your anonymous delegate. Use tool like refelector to understand the code that it is generating. The following will fix your problem:

static void Main() 
        {
            for (int i = 0; i < 10; i++)
            {
                int capture = i;
                new Thread(() => Console.Write(capture)).Start();
            }
        } 

幕后

每当您在匿名委托中使用外部作用域中的变量(在您的情况下为变量 i)时,编译器都会生成一个新类,该类包装匿名函数以及它在外部作用域中使用的数据.因此,在您的情况下,生成的类包含 - 一个函数和数据成员来捕获变量 i 的值.类定义类似于:

Whenever you use a variable from outer scope (in your case variable i) in anonymous delegate, the compiler generates a new class that wraps anonymous function along with the data that it uses from the outer scope. So in your case the generated class contains - one function and data member to capture the value of variable i. The class definition looks something like:

class SomeClass
{
    public int i { get; set; }

    public void Write()
    {
        Console.WriteLine(i);
    }
}

编译器将您的代码重写如下:

The compiler re-writes your code as follows:

SomeClass someObj = new SomeClass();
for (int i = 0; i < 10; i++)
{
    someObj.i = i;
    new Thread(someObj.Write).Start();
}

因此是您面临的问题.当您捕获一个变量时,编译器会执行以下操作:

and hence the problem - that you are facing. When you capture a variable, the compiler does the following:

for (int i = 0; i < 10; i++)
{
    SomeClass someObj = new SomeClass();
    someObj.i = i;
    new Thread(someObj.Write).Start();
}

注意 SomeClass 实例化的区别.当您捕获一个变量时,它会创建与迭代次数一样多的实例.如果您不捕获变量,它会尝试对所有迭代使用相同的实例.

Note the difference in SomeClass instantiation. When you capture a variable, it creates as many instances as there are number of iterations. If you do not capture a variable, it tries to use the same instance for all iterations.

希望以上的解​​释能解开你的疑惑.

Hope, the above explanation will clarify your doubt.

谢谢

这篇关于关于Thread中传递的局部变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆