moh*_*691 1 .net c# variables multithreading
我很难理解以下程序的意外输出:
class ThreadTest
{
static void Main()
{
for(int i = 0; i < 10; i++)
new Thread(() => Console.Write(i)).Start();
}
}
Run Code Online (Sandbox Code Playgroud)
查询:运行在不同线程的不同代码有不同的堆栈?如果是,那么变量应该保留它们的值,因为 int 是值类型?
每个线程都有自己的堆栈。您面临的问题与堆栈无关。问题在于它为匿名委托生成代码的方式。使用 reflector 之类的工具来理解它生成的代码。以下将解决您的问题:
static void Main()
{
for (int i = 0; i < 10; i++)
{
int capture = i;
new Thread(() => Console.Write(capture)).Start();
}
}
Run Code Online (Sandbox Code Playgroud)
引擎盖下
每当您在匿名委托中使用外部作用域中的变量(在您的情况下为变量 i)时,编译器都会生成一个新类,该类包装匿名函数以及它在外部作用域中使用的数据。因此,在您的情况下,生成的类包含 - 一个函数和数据成员来捕获变量 i 的值。类定义类似于:
class SomeClass
{
public int i { get; set; }
public void Write()
{
Console.WriteLine(i);
}
}
Run Code Online (Sandbox Code Playgroud)
编译器按如下方式重写您的代码:
SomeClass someObj = new SomeClass();
for (int i = 0; i < 10; i++)
{
someObj.i = i;
new Thread(someObj.Write).Start();
}
Run Code Online (Sandbox Code Playgroud)
因此问题 - 您面临的问题。当您捕获一个变量时,编译器会执行以下操作:
for (int i = 0; i < 10; i++)
{
SomeClass someObj = new SomeClass();
someObj.i = i;
new Thread(someObj.Write).Start();
}
Run Code Online (Sandbox Code Playgroud)
注意 SomeClass 实例化的区别。当您捕获一个变量时,它会创建与迭代次数一样多的实例。如果您不捕获变量,它会尝试对所有迭代使用相同的实例。
希望以上的解释能解开你的疑惑。
谢谢