线程输入参数

mar*_*adi 2 c# multithreading thread-safety visual-studio

我想在线程列表中运行具有不同值的类.像这样 :

     int index = 0;
     foreach (TreeNode nd in tvew.Nodes[0].Nodes)
     {
         threadping[index] = new Thread(delegate()
         { this.Invoke(new DelegateClientState(InvokeCheckNetworkState), new object[] {nd}); });

         threadping[index].Name = nd.Name;
         threadping[index].IsBackground = true;
         threadping[index].Start();

         index++;
     }
Run Code Online (Sandbox Code Playgroud)

但是当我调试代码时,我看到class参数只是最后一个值.我的意思是当我通过线程类时,我看到每次该类运行输入参数的值是最后一个线程的最后一个值.

任何人都可以告诉我为什么?

dri*_*iis 5

这是因为nd变量是在闭包中捕获的.当线程运行时,它们都引用相同的TreeNode实例,即分配给的最后一个实例nd.要修复,请使用在范围内不会更改的单独变量:

 foreach (TreeNode nd in tvew.Nodes[0].Nodes)
 {
     var current = nd;
     threadping[index] = new Thread(delegate()
     { this.Invoke(new DelegateClientState(InvokeCheckNetworkState), new object[] {current}); });
Run Code Online (Sandbox Code Playgroud)

如果我们得到编译器技术,这是因为编译器生成一个包含你的循环变量的匿名类,以使其可供线程委托访问.这是预期的行为,但是当你第一次碰到它时可能有点违反直觉.

有关闭包和变量捕获的更长解释,请参阅Jon Skeet文章中的Captured Variables部分(底部)Eric Lippert的这篇文章.这通常被称为"访问修改后的闭包"错误.如果您在StackOverflow或Google上搜索该术语,您将获得大量的点击来解释它.