static async Task Main(string[] args) { for (int i = 0; i < 3; i++) { Task.Run(() => { T(i); }); // Thread.Sleep(1); } Console.ReadLine(); void T(int i) { Thread.Sleep(2000); Console.WriteLine($"内部:{i}"); } }
上图代码 运行结果是这样的
然后把注释去掉
Thread.Sleep(1);
结果是这样的
出现这样的结果: 应该是这3次循环中, i 指向的内存地址都是一样的,并且task.run里面是异步,它会立刻返回(因此会导致循环结束了,但是task.run里面的其实还没正式开始运行,因此 i 就是最后一次循环的值,那么内部方法T赋值的 i 也是最后一次循环的值,所以呈现出结果都是3).
而加入 Thread.Sleep(1) 可以让执行的时间相对延长一点,导致内部T赋值的 i 有时间可以赋值,所以呈现结果就是0,1,2
额外内容:
for (int i = 0; i < 3; i++) { int a = i; Task.Run(() => { T(a); }); //Thread.Sleep(1); }
用一个中间变量赋值,因为此处是值类型是完全复制的,因此不会出现 i 的引用的问题(有点类似js的闭包),以下是结果