For循环超出范围
本文关键字:范围 循环 For | 更新日期: 2023-09-27 17:58:15
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
MyClass myClass = new MyClass();
myClass.StartTasks();
}
}
class MyClass
{
int[] arr;
public void StartTasks()
{
arr = new int[2];
arr[0] = 100;
arr[1] = 101;
for (int i = 0; i < 2; i++)
{
Task.Factory.StartNew(() => WorkerMethod(arr[i])); // IndexOutOfRangeException: i==2!!!
}
}
void WorkerMethod(int i)
{
}
}
}
似乎在循环迭代完成之前,i++又被执行了一次。为什么我会得到IndexOutOfRangeException?
您正在结束循环变量。当调用WorkerMethod
时,i
的值可以是2,而不是0或1。
当您使用闭包时,重要的是要理解您目前没有使用变量的值,而是使用变量本身。所以,如果你在循环中创建这样的lambdas:
for(int i = 0; i < 2; i++) {
actions[i] = () => { Console.WriteLine(i) };
}
然后执行这些操作,它们都会打印"2",因为这就是i
目前的值。
在循环中引入局部变量将解决您的问题:
for (int i = 0; i < 2; i++)
{
int index = i;
Task.Factory.StartNew(() => WorkerMethod(arr[index]));
}
<Resharper插头>这是尝试Resharper的又一个原因——它给出了很多警告,帮助你尽早发现像这样的错误。"关闭循环变量"就是其中之一<Resharper插头>
原因是在并行任务中使用了循环变量。因为任务可以并发执行,所以循环变量的值可能与启动任务时的值不同。
您在循环中启动了任务。当任务开始查询循环变量时,循环已经结束,因为变量i现在已经超过了停止点。
即:
- i=2并且循环退出
- 任务使用变量i(现在为2(
您应该使用Parallel.For来并行执行循环体。以下是如何使用Parallel的示例。对于
或者,如果你想保持当前的结构,你可以将i的副本复制到循环局部变量中,循环局部副本将在并行任务中保持其值。
例如
for (int i = 0; i < 2; i++)
{
int localIndex = i;
Task.Factory.StartNew(() => WorkerMethod(arr[localIndex]));
}