1 static void Main(string[] args) 2 { 3 Task[] tasks = new Task[10]; 4 int[] numbers = new int[10] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; 5 for (int i = 0; i < tasks.Length; i++) 6 { 7 // int number = numbers[i]; 8 tasks[i] = Task.Run(() => 9 { 10 Console.WriteLine("Number:{0}", numbers[i]); // 索引超出了数组界限。i会一直是10 11 //Console.WriteLine("Number:{0}", number); //这样就正常 12 }); 13 } 14 Console.ReadLine(); 15 }
static void Main(string[] args) { int[] numbers = new int[10] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; List<int> numberList = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; Dictionary<int, int> dict = new Dictionary<int, int> { { 1, 1 }, { 2, 2 }, { 3, 3 }, { 4, 4 }, { 5, 5 } }; HashSet<int> hashNumber = new HashSet<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; /*全是1*/ for (int i = 0; i < hashNumber.Count; i++) { Task.Run(() => { Console.WriteLine("number:{0}", hashNumber.ElementAt(0)); }); } /*无错*/ foreach (var number in hashNumber) { Task.Run(() => { Console.WriteLine("number:{0}", number); }); } /*输出全是5*/ for (int i = 0; i < dict.Count; i++) { Task.Run(() => { Console.WriteLine("number:{0}", dict[i]); }); } /*无错*/ foreach (var number in numbers) { Task.Run(() => { Console.WriteLine("number:{0}", number); }); } /*无错*/ foreach (var dic in dict) { Task.Run(() => { Console.WriteLine("number:{0}", dic.Value); }); } Console.WriteLine("完成"); Console.ReadLine(); }
经过测试,for循环的i内存地址不是独立的,所以被覆盖,foreach的item是单独分配了内存,在整个方法没有执行结束前不会销毁!SO!
这是正常的,Task.Run
是在新的线程中异步执行的,在 for 循环中 Task 并不会立即执行,“i会一直是10”说明 for 循环结束后,Task 才开始执行,这时 i 的值正好是 10 。
是!,恍然大悟
这说明 i 的值没有被捕获到 Task 的执行上下文中,也就是说 i 变量的值不在捕获范围内,要想让 i 被捕获,需要引入中间变量,下面的代码就可以正常执行
static void Main(string[] args)
{
Task[] tasks = new Task[10];
int[] numbers = new int[10] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
for (int i = 0; i < tasks.Length; i++)
{
var j = i;
tasks[i] = Task.Run(() =>
{
Console.WriteLine("Number:{0}", numbers[j]);
});
}
Console.ReadLine();
}
@PingMac: for 循环结束 i 的值就是 10
@dudu: 恩,理解了,将i赋值给j,得到新的内存