我对多线程编程感到不舒服,当我尝试在我的代码中实现它时,遇到了一个我无法弄清楚原因的异常。任何帮助都将非常感谢:) 所以,基本上我有一小段代码:
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#。
谢谢
答案 0 :(得分:3)
您有“结束循环变量”问题,请检查:closing over the loop variable considered harmful和The 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命名空间中的ConcurrentBag
或BlockingCollection
,它们使线程编程更容易。
答案 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();
}