Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# ParameterizedThreadStart中捕获的变量_C#_Multithreading_Captured Variable - Fatal编程技术网

C# ParameterizedThreadStart中捕获的变量

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);

我有以下代码,创建了10个线程,这些线程将消息写入控制台:

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));
    }                           
});