多线程程序中的索引超出范围异常
本文关键字:范围 异常 索引 程序 多线程 | 更新日期: 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命名空间中的ConcurrentBag
或BlockingCollection
,它们使线程编程更容易。
请尝试以下操作
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();
}