我有一个线程数组,需要在完成工作后返回一些值。 如果我创建单独的线程变量但不通过循环,一切正常。
public temp ()
{
int count = 10; // comes from function
int[] ret = new int[count] // return value array
Cls[] cls = new Cls[count]; // Class instance array
Thread[] threads = new Thread[count]; // threads array
// Main LOOP
for (int i = 0; i < count; i++)
{
cls[i] = new Cls('\0', 1); // create new class instances
threads[i] = new Thread(state =>
{
ret[i] = cls.SomeMethod('some', 'thing'); // SomeMethod returns int which I need to store
});
}
// *** 1st TRY ***
//-----------------------
for (int i = 0; i < count; i++)
{
threads[i].Start() // (error)
}
// *** 2nd TRY ***
//------------------------
threads[0].Start();
threads[1].Start();
//.....
}
第一次尝试: 出于某种原因,当我到达(第二个)循环中的线程[i] .Start()时,它会给出数组'Out of bound'错误,因为i(主循环)变为3 ....为什么&amp;怎么样?
第二次尝试:错误:系统.__ ComObject无法转换为接口...(&lt; - 此错误是 不是我的问题的一部分。)我的问题是:
如果我单独分配/启动线程(不是循环),如
thread1 = {...};
thread2 = {...} ...然后启动每个帖子
thread1.Start();
thread2.Start(); ....一切顺利,但为什么不从循环???
答案 0 :(得分:3)
您 closing over the loop counter 。
基本上,将其更改为:
// Main LOOP
for (int i = 0; i < count; i++)
{
// this is fine referring to i, because it's not in a lambda:
cls[i] = new Cls('\0', 1);
int j = i; // create a new variable for the lambda
threads[i] = new Thread(state =>
{
// here you must refer to j, not i, because you're in a lambda
ret[j] = cls.SomeMethod('some', 'thing');
});
}
正在发生的事情是,lamda表达式中的代码是指i
变量,而不是i
当前的值你创建线程。它们都指的是内存中的相同变量。
因此,当您启动线程时,i
等于count
,当您的线程代码尝试访问ret[i]
时,您的索引将超出范围。