2011-11-06 48 views
2

我想在线程列表中运行具有不同值的类。像这样:线程输入参数

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

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

有人可以告诉我为什么?

+0

你可以显示你已经初始化threadPing集合的代码。什么是“类参数”或者你正在调试什么线程类? –

回答

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

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

有关闭包和变量捕获的更长解释,请参阅see the Captured Variables section here (bottom section) in a Jon Skeet articlethis article from Eric Lippert。这通常称为“访问修改的关闭”错误。如果你在StackOverflow或Google上搜索这个词,你会得到很多解释它的命中。

+0

tnx,它的工作原理。另一个问题:为什么我的线程不能同时工作?我在第一个循环结束时提出的“InvokeCheckNetworkState”的第一行指向断点。就像线程等待上一个线程完成一样。我的意思是你不同时工作。我该怎么办? –