无法从循环中启动/执行线程数组

时间:2013-04-11 00:56:45

标签: c# multithreading lambda

我有一个线程数组,需要在完成工作后返回一些值。 如果我创建单独的线程变量但不通过循环,一切正常。

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(); ....一切顺利,但为什么不从循环???

1 个答案:

答案 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]时,您的索引将超出范围。