多线程程序中的IndexOutOfRange异常

时间:2013-08-06 03:30:58

标签: c# multithreading exception indexoutofboundsexception

我对多线程编程感到不舒服,当我尝试在我的代码中实现它时,遇到了一个我无法弄清楚原因的异常。任何帮助都将非常感谢:) 所以,基本上我有一小段代码:

string[][] Array1 = new string[thread_count][];

/* Logic to insert data in Array1 */

Thread[] WorkerThreads = new Thread[thread_count];

for (int i = 0; i < thread_count; i++)
{
    /* THE EXCEPTION OCCURS IN THE FOLLOWING LINE */
    WorkerThreads[i] = new Thread(() => GetVal(Array1[i], val, num));
    WorkerThreads[i].Start();
}

for (int i = 0; i < WorkerThreads.Length; i++)
    WorkerThreads[i].Join();  

现在,thread_count的值设置为10,我得到一个IndexOutOfRange异常。调试器将i的值显示为10,并且Array1 [10] []是它尝试访问的值 当循环不应该跑到那么远的时候,我没有得到i的值如何达到10 任何人都可以指出我哪里出错了?我正在使用C#。

谢谢

5 个答案:

答案 0 :(得分:3)

您有“结束循环变量”问题,请检查:closing over the loop variable considered harmfulThe foreach identifier and closures

添加一个临时变量来修复它:

for (int i = 0; i < thread_count; i++)
{
    var j = i;
    /* THE EXCEPTION OCCURS IN THE FOLLOWING LINE */
    WorkerThreads[j] = new Thread(() => GetVal(Array1[j], val, num));
    WorkerThreads[j].Start();
}

答案 1 :(得分:2)

您的问题是您正在创建的lambda /匿名函数。变量i在循环退出之前获得值10。当您致电new Thread(() => GetVal(Array1[i], val, num));时,您实际上并未调用相关代码。匿名函数保留对变量i的引用,当您尝试启动该线程时,它会查找引用,看它的值为10,然后就会出现异常。

请参阅此网页的“Lambda表达式中的可变范围”部分:http://msdn.microsoft.com/en-us/library/vstudio/bb397687.aspx

答案 2 :(得分:1)

您可能遇到竞争条件,尝试使用System.Collections.Concurrent命名空间中的ConcurrentBagBlockingCollection,它们使线程编程更容易。

答案 3 :(得分:1)

尝试以下

for (int i = 0; i < thread_count; i++)
{
    int copy = i;
    WorkerThreads[copy] = new Thread(() => GetVal(Array1[copy], val, num));
    WorkerThreads[copy].Start();
}

答案 4 :(得分:0)

GetVal(Array[i])导致变量i闭包,在创建线程之前,我将等于thread_count。在这种情况下,所有主题都将GetVal(Array[10]),因为它们都引用了最新的i变量。

要解决此问题,请在Array[i]中使用之前创建分配给GetVal的变量:

for (int i = 0; i < thread_count; i++)
{
    string[] value = Array1[i];

    WorkerThreads[i] = new Thread(() => GetVal(value, val, num));
    WorkerThreads[i].Start();
}