在C#中,带有for循环的异步方法是如何工作的?

huangapple go评论79阅读模式
英文:

How does async methods with for loops work in C#?

问题

我有一个C#代码,如下所示:

FirstMethod();
Console.WriteLine("OK");
Console.ReadKey();

static async void FirstMethod()
{
    for(int i = 0; i < 10; i++)
        await FileLengthAwaiter(i);
}

static async Task FileLengthAwaiter(int i)
{
    Console.WriteLine($"start method {i}");
    await Task.Delay(1000);
    Console.WriteLine($"end method {i}");
}

当我运行这段代码时,在for循环的第一次迭代中,当i等于0时,通过运行await语句,方法'FirstMethod'将返回,并且Console语句将打印"OK"。
但是对于剩余的for循环迭代,运行await语句时,它会返回方法'FirstMethod',但不会打印"OK"。为什么会这样?我希望代码在每次for循环迭代时都运行Console语句并打印"OK"。但这并没有发生。有人能帮我吗?
输出如下:

start method 0
OK
end method 0
start method 1
end method 1
start method 2
end method 2
start method 3
end method 3
start method 4
end method 4
start method 5
end method 5
start method 6
end method 6
start method 7
end method 7
start method 8
end method 8
start method 9
end method 9
英文:

I have a code in C# like this:

FirstMethod();
Console.WriteLine(&quot;OK&quot;);
Console.ReadKey();

static async void FirstMethod()
{
    for(int i = 0; i &lt; 10; i++)
        await FileLengthAwaiter(i);
}

static async Task FileLengthAwaiter(int i)
{
    Console.WriteLine($&quot;start method {i}&quot;);
    await Task.Delay(1000);
    Console.WriteLine($&quot;end method {i}&quot;);
}

When I run this code, in the first iteration of the for loop, when i equals to 0, by running the await statement, the method 'FirstMethod' will return and the "OK" will be printed by the Console statement.
But for the remained iterations of the for loop, when running the await statement, it returns the method 'FirstMethod', but it doesn't print the "OK".
Why does this happen? I expect the code to run the Consule statement and prints "OK" for each iteration of the for loop. But it doesn't happen.
Could anyone help me?
The output is like this:

start method 0
OK
end method 0
start method 1
end method 1
start method 2
end method 2
start method 3
end method 3
start method 4
end method 4
start method 5
end method 5
start method 6
end method 6
start method 7
end method 7
start method 8
end method 8
start method 9
end method 9

答案1

得分: 1

FirstMethod();

这将运行该方法中的代码,直到它到达第一个 await,即当它到达 Task.Delay(1000) 时,它将打印 "start method 0"。由于 FirstMethod() 没有被等待,主线程将继续运行其余的代码。也就是说:

Console.WriteLine("OK");
Console.ReadKey();

然后主线程将在 ReadKey 中卡住。在经过1000毫秒后,Task.Delay 将完成,执行将在一个线程池线程上恢复,然后打印 "end method 0"。然后它将继续执行,直到达到下一个 Task.Delay。此时线程池线程将被返回到池中,直到任务完成为止。

在循环最终完成后,不会发生任何其他事情,由于 FirstMethod() 不返回任何任务,因此无法检查方法是否实际达到了循环的末尾或以某种方式失败。有时这被称为 "fire and forget",在按钮事件处理程序之外或类似的情况下应避免使用。

由于 Console.WriteLine("OK") 不在循环内,因此它不应该打印多次。

如果您想了解有关异步等待的实现方式的更多信息,我建议阅读 C# 中异步方法的解析

英文:

> FirstMethod();

This will run the code in the method until it gets to the first await, i.e. when it gets to Task.Delay(1000), so it will print &quot;start method 0&quot;. Since FirstMethod() is not awaited, the main thread will then continue to run the rest of the code. I.e.

Console.WriteLine(&quot;OK&quot;);
Console.ReadKey();

The main thread will then get stuck inside ReadKey. After 1000ms has elapsed the Task.Delay will complete, and the execution will continue where it left of, on a thread pool thread, and print "end method 0". It will then continue until it gets to the next Task.Delay. At that point the threadpool thread will just be returned back to the pool until the task completes.

After the loop eventually completes nothing more will happen, and since FirstMethod() does not return any task there will be no way to check if the method actually reached the end of the loop or somehow failed. This is sometimes called "fire and forget", and should be avoided outside of button event handlers or similar.

Since the Console.WriteLine(&quot;OK&quot;) is not inside the loop it should not print more than once.

If you want to read more about how async await is implemented I would recommend reading Dissecting the async methods in C#

huangapple
  • 本文由 发表于 2023年7月31日 21:51:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/76804298.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定