【问题标题】:Can't start/execute an array of threads from a loop无法从循环中启动/执行线程数组
【发布时间】:2013-04-11 00:56:44
【问题描述】:

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

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 无法转换为接口...(

如果我像

那样单独分配/启动线程(不在循环中)

thread1 = {...};

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

thread1.Start();

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

【问题讨论】:

    标签: c# multithreading lambda


    【解决方案1】:

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

    【讨论】:

    • 感谢博尔格胡德!这让我很快乐。真的很感激:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-04
    • 2015-09-30
    • 2020-10-04
    • 1970-01-01
    • 2013-07-20
    相关资源
    最近更新 更多