0

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

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()时,它会给出数组“超出范围”错误,因为 i(主循环的)变为 3 .... 为什么以及如何?

第二次尝试:错误:System.__ComObject 无法转换为接口...(<-此错误不是我的问题的一部分。)我的问题是:

如果我分别分配/启动线程(不在循环中),例如

线程1 = {...};

thread2 = {...} ... 然后启动每个线程

thread1.Start();

thread2.Start(); ....一切顺利,但为什么不从循环?

4

1 回答 1

3

您正在关闭循环计数器

基本上,将其更改为:

// 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]

于 2013-04-11T01:02:59.463 回答