多线程程序中的索引超出范围异常

本文关键字:范围 异常 索引 程序 多线程 | 更新日期: 2023-09-27 18:26:30

我对多线程编程不太满意,当我尝试在我的代码中实现它时,遇到了一个异常,我无法弄清楚为什么。任何这方面的帮助将不胜感激:)
所以,基本上我有一小段代码:

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#。

谢谢

多线程程序中的索引超出范围异常

您有"关闭循环变量"问题,请检查以下内容:关闭被认为是有害的循环变量和 foreach 标识符和闭包。

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

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();
}

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

请参阅本网页的"Lambda 表达式中的变量作用域"部分:http://msdn.microsoft.com/en-us/library/vstudio/bb397687.aspx

您可能会

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

请尝试以下操作

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

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

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

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