C# ParameterizedThreadStart中捕获的变量
我有以下代码,创建了10个线程,这些线程将消息写入控制台:C# ParameterizedThreadStart中捕获的变量,c#,multithreading,captured-variable,C#,Multithreading,Captured Variable,我有以下代码,创建了10个线程,这些线程将消息写入控制台: for (int i = 0; i < 10; i++) { { Thread thread = new Thread((threadNumber) => { for (int j = 0; j < 10; j++) { Thread.Sleep(200);
for (int i = 0; i < 10; i++)
{
{
Thread thread = new Thread((threadNumber) =>
{
for (int j = 0; j < 10; j++)
{
Thread.Sleep(200);
Console.WriteLine(string.Format("Thread: {0}, Line: {1}", threadNumber, j));
}
});
thread.Start(i);
}
}
for(int i=0;i<10;i++)
{
{
线程=新线程((线程编号)=>
{
对于(int j=0;j<10;j++)
{
睡眠(200);
WriteLine(string.Format(“Thread:{0},Line:{1}”,threadNumber,j));
}
});
线程启动(i);
}
}
我的理解是
ParameterizedThreadStart
获取一个对象,该对象的引用副本被发送到线程。如果是这种情况,因为我没有在每个循环中创建I
的本地副本,那么所有新线程都将指向相同的内存位置,这意味着某些线程编号可能会“丢失”。尽管如此(甚至针对大量线程/睡眠时间)运行后,i
的每个值都有自己的线程。有人能解释一下原因吗?您没有应用任何延迟或“捕获”的内容,即创建一个匿名函数来包装i
此处的lambda函数不引用任何地方的i
,其状态完全内部化/包含,因此此处没有问题:
(threadNumber) =>
{
for (int j = 0; j < 10; j++)
{
Thread.Sleep(200);
Console.WriteLine(string.Format("Thread: {0}, Line: {1}", threadNumber, j));
}
});
按值传递i
(即复制其值),因为它是一种“值类型”,并且不会在任何类型的匿名函数中捕获。从这个意义上讲,它就像任何普通的struct
一样被传递给任何普通的方法(因为这正是正在发生的事情)
如果您使用
i
而不是threadNumber
来编写lambda:
{
for (int j = 0; j < 10; j++)
{
Thread.Sleep(200);
Console.WriteLine(string.Format("Thread: {0}, Line: {1}", i, j));
}
});
{
对于(int j=0;j<10;j++)
{
睡眠(200);
WriteLine(string.Format(“线程:{0},行:{1}”,i,j));
}
});
那你就有麻烦了。在这种情况下,
i
指的是原始变量位置,并将在线程执行时进行计算。这意味着它可能是创建时i
的当前值(不太可能只是由于处理时间),也可能是后来在for
循环中设置的值,或者是最后一个可能的值10
,并且很可能在迭代之间跳过或共享该数字。感谢您的详细解释,这是复制价值的一部分,是绊倒了我@特立独行的注释即使在他给出的“错误”案例中,您仍然可以通过在闭包之前添加一行var i1=i
并在您使用i
的任何地方使用i1
来获得正确的结果。
{
for (int j = 0; j < 10; j++)
{
Thread.Sleep(200);
Console.WriteLine(string.Format("Thread: {0}, Line: {1}", i, j));
}
});