public void GatherDataFromSwitches(Device[] switches)
{
List<Thread> workerThreads = new List<Thread>();
for(int i = 0; i < switches.Length - 1; i++)
{
Thread t = new Thread(unused => GatherDataFromSwitch(switches[i]));
workerThreads.Add(t);
t.Start();
}
foreach (Thread d in workerThreads) d.Join(); //wait for all threads to finish
}
如果我在运行该方法之后循环切换,我注意到某些交换机没有添加数据,并且一些交换机从多个交换机添加了数据。因此将引用传递给工作线程出了问题。我还不确定到底是什么,但我通过添加
解决了这个问题Thread.Sleep(100);
之后
t.Start();
我假设这是有效的,因为现在新创建的线程有一些时间在创建下一个之前进行初始化。但这是一个解决方法,而不是修复。是因为lambda表达式如何工作?
我如何妥善解决这个问题?
答案 0 :(得分:3)
问题是在lambda中捕获i
的方式。在循环中创建一个本地副本,让每个lambda捕获一个不同的值:
public void GatherDataFromSwitches(Device[] switches)
{
List<Thread> workerThreads = new List<Thread>();
for(int i = 0; i < switches.Length ; i++)
{
int j = i; // local i
Thread t = new Thread(unused => GatherDataFromSwitch(switches[j]));
workerThreads.Add(t);
t.Start();
}
foreach (Thread d in workerThreads) d.Join(); //wait for all threads to finish
}
或者明确地将i
作为参数传递给线程:
public void GatherDataFromSwitches(Device[] switches)
{
List<Thread> workerThreads = new List<Thread>();
for(int i = 0; i < switches.Length ; i++)
{
Thread t = new Thread(param => { j = (int)param; GatherDataFromSwitch(switches[j]); });
workerThreads.Add(t);
t.Start(i);
}
foreach (Thread d in workerThreads) d.Join(); //wait for all threads to finish
}
答案 1 :(得分:0)
public void GatherDataFromSwitches(Device[] switches) {
List<Thread> workerThreads = new List<Thread>();
for(int i = 0; i < switches.Length ; i++)
{
int j = i;
Thread t = new Thread(unused => GatherDataFromSwitch(switches[j]));
workerThreads.Add(t);
t.Start();
}
foreach (Thread d in workerThreads) d.Join(); //wait for all threads to finish
}
请注意将i
复制到j
。如果你有resharper,你的代码会产生警告,更多关于这个问题Access to Modified Closure