C# 多线程程序中的IndexOutfrange异常
我对多线程编程不是很熟悉,当我试图在代码中实现它时,遇到了一个异常,我不知道为什么。在此方面的任何帮助都将不胜感激:)C# 多线程程序中的IndexOutfrange异常,c#,multithreading,exception,indexoutofboundsexception,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
基本上,我有一小段代码:
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();
string[][]Array1=新字符串[线程计数][];
/*在数组1中插入数据的逻辑*/
线程[]WorkerThreads=新线程[线程计数];
对于(int i=0;iGetVal(Array1[i],val,num));
WorkerThreads[i].Start();
}
for(int i=0;i
现在,thread_count的值被设置为10,我得到一个indexoutfrange异常。调试器将i的值显示为10,而Array1[10][]是它试图访问的数组。当循环不应该运行那么远时,我不知道I的值如何达到10。
有人能指出我哪里出了问题吗?我用的是C#
感谢您,您可能遇到了竞争条件,请尝试从命名空间中使用
ConcurrentBag
或BlockingCollection
,它们使线程编程更容易。如果您遇到了“closing over loop variable”问题,请检查此项:和
添加临时变量以修复它:
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();
}
for(int i=0;iGetVal(Array1[j],val,num));
WorkerThreads[j].Start();
}
您的问题是正在创建的lambda/匿名函数。在循环退出之前,变量i
的值为10。调用新线程(()=>GetVal(Array1[i],val,num))代码>,您实际上没有调用有问题的代码。匿名函数保留对变量i
的引用,当您尝试启动线程时,它会查找该引用,发现其值为10,然后您会得到异常
请参阅本网页的“Lambda表达式中的变量范围”部分:请尝试下面的内容
for (int i = 0; i < thread_count; i++)
{
int copy = i;
WorkerThreads[copy] = new Thread(() => GetVal(Array1[copy], val, num));
WorkerThreads[copy].Start();
}
for(int i=0;iGetVal(Array1[copy],val,num));
WorkerThreads[copy].Start();
}
GetVal(数组[i])
导致变量i
关闭,在创建线程之前,该变量将等于线程计数。在这种情况下,所有线程都将具有GetVal(数组[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();
}
for(int i=0;iGetVal(value,val,num));
WorkerThreads[i].Start();
}
我认为闭包都引用了相同的变量I
——而不是该循环中的值I
。但是为什么创建一个temp变量j
会从根本上改变绑定/作用域的方式呢?因为“j”在循环中具有局部作用域,因此会为循环的每个迭代创建一个新的“j”。每个lambda表达式都有自己的副本。虽然“i”在循环的外部作用域中,所以变量在每次迭代中都会被重用,每个lambda表达式都会得到相同的变量,在循环之后也会被重用。感谢@fcuesta——我可以从逻辑上分析,但我不确定我是否直观地得到了它:)我相信Javascript中也会出现同样的情况,特别是在jQuery“handler”中功能。