Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/296.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 多线程程序中的IndexOutfrange异常_C#_Multithreading_Exception_Indexoutofboundsexception - Fatal编程技术网

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”中功能。