很抱歉,如果之前有人询问过。 我有两个几乎相同的函数sync和async:
private static void runLong(int id)
{
Console.WriteLine("starting " + id );
Thread.Sleep(myRandom.Next(200,1000));
Console.WriteLine("-exiting " + id);
}
private static async Task runLongAsync(int id)
{
Console.WriteLine("starting " + id );
await Task.Run(()=>Thread.Sleep(myRandom.Next(200,1000)));
Console.WriteLine("-exiting " + id );
}
我以非常类似的方式打电话给他们:
public static void run()
{
run().Wait();
runAsync().Wait();
}
private static async Task run()
{
List<Task> runningTasks = new List<Task>();
for (int i = 0; i < 5; i++)
{
runningTasks.Add(Task.Run(() => runLong(i)));
}
await Task.WhenAll(runningTasks);
}
private static async Task runAsync()
{
List<Task> runningTasks = new List<Task>();
for (int i = 0; i < 5; i++)
{
runningTasks.Add(runLongAsync(i));
}
await Task.WhenAll(runningTasks);
}
但结果不同: 异步调用同步函数
调用异步函数:
即。在第一种情况下,参数被覆盖,但在第二种情况下 - 它们不是。这是怎么回事?
Edit1:是的我找到了一个快速修复 int copy = i; 但我想了解这里实际发生了什么以及为什么这两个函数的行为不同。
Edit2:@Servy引用的文章解释了为什么 for 和 foreach 循环的行为不同,在我的情况下我有两个 for 循环表现不同
答案 0 :(得分:0)
捕获的变量。每个循环迭代i
此处不,因此它会在启动时获取当前值 - 这可能是5
:
for (int i = 0; i < 5; i++)
{
runningTasks.Add(Task.Run(() => runLong(i)));
}
解决方法是在循环内提升值:
for (int i = 0; i < 5; i++)
{
var j = i;
runningTasks.Add(Task.Run(() => runLong(j)));
}
这里重点是j
现在在循环中 ,因此捕获的变量上下文特定于该迭代。