将值类型 (int) 传递给异步方法不会复制该值
Passing a value type (int) to async method don't make a copy of the value
static void Main(string[] args)
{
Program p = new Program();
p.TestAsyncInLoop();
}
private void TestAsyncInLoop()
{
var tasks = new List<Task>();
for (int i = 0; i < 20; i++)
{
//tasks.Add(Task.Run(() => PrintNo(i)));
var ii = i;
tasks.Add(Task.Run(() => PrintNo(ii)));
}
Task.WaitAll(tasks.ToArray());
}
private async Task PrintNo(int no)
{
Console.WriteLine(no);
}
在 for 循环中,我正在调用一个异步方法 "PrintNo(int no)" 传递一个参数 "i",它是值类型 (int)。
当方法开始执行时,"no"的值等于currenti的值(大概是20)不是最初在循环中发送的值!我做的一个解决方案是在发送到新变量 "ii" 之前复制 "i" 的值。这个解决方案工作正常,但你能解释为什么 "i" 的值 没有复制 到同步方法中的方法吗? (不工作的代码是 //commented)
您对行为的解释略有偏差。您没有在循环中调用该函数。调用在 lambda 内部。参数传递是完全可以的,而且是有价值的。 i
的捕获是问题所在。这与异步无关。
自 C# 5 起,此问题已通过 foreach
修复。使用 foreach
.
作为主观意见,我觉得自从我们有了 LINQ 以来,for
循环主要变成了一种代码味道。很难看到它们的真正用例。我想这里可以作为计数循环。
static void Main(string[] args)
{
Program p = new Program();
p.TestAsyncInLoop();
}
private void TestAsyncInLoop()
{
var tasks = new List<Task>();
for (int i = 0; i < 20; i++)
{
//tasks.Add(Task.Run(() => PrintNo(i)));
var ii = i;
tasks.Add(Task.Run(() => PrintNo(ii)));
}
Task.WaitAll(tasks.ToArray());
}
private async Task PrintNo(int no)
{
Console.WriteLine(no);
}
在 for 循环中,我正在调用一个异步方法 "PrintNo(int no)" 传递一个参数 "i",它是值类型 (int)。 当方法开始执行时,"no"的值等于currenti的值(大概是20)不是最初在循环中发送的值!我做的一个解决方案是在发送到新变量 "ii" 之前复制 "i" 的值。这个解决方案工作正常,但你能解释为什么 "i" 的值 没有复制 到同步方法中的方法吗? (不工作的代码是 //commented)
您对行为的解释略有偏差。您没有在循环中调用该函数。调用在 lambda 内部。参数传递是完全可以的,而且是有价值的。 i
的捕获是问题所在。这与异步无关。
自 C# 5 起,此问题已通过 foreach
修复。使用 foreach
.
作为主观意见,我觉得自从我们有了 LINQ 以来,for
循环主要变成了一种代码味道。很难看到它们的真正用例。我想这里可以作为计数循环。