且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

C#异步/等待控制台应用程序中的奇怪行为

更新时间:2022-12-21 14:20:29

异步等待不是这样有效。

将方法标记为 async 不会创建任何后台线程。当您调用 async 方法时,它会同步运行直到异步点,然后才返回到调用方。

Marking a method as async doesn't create any background threads. When you call an async method it runs synchronously until an asynchronous point and only then returns to the caller.

异步点是当您 await 尚未完成的任务时。完成后,该方法的其余部分将按计划执行。此任务应该表示实际的异步操作(例如I / O或 Task.Delay )。

That asynchronous point is when you await a task that haven't completed yet. When it does complete the rest of the method is scheduled to be executed. This task should represent an actual asynchronous operation (like I/O, or Task.Delay).

在您的代码没有异步点,也没有返回调用线程的点。线程变得越来越深,并在 Thread.Sleep 上阻塞,直到这些方法完成并返回 DoAsync

In your code there is no asynchronous point, there's no point in which the calling thread is returned. The thread just goes deeper and deeper and blocks on Thread.Sleep until these methods are completed and DoAsync returns.

以这个简单示例为例:

public static void Main()
{
    MainAsync().Wait();
}

public async Task MainAsync()
{
    // calling thread
    await Task.Delay(1000);
    // different ThreadPool thread
}

这里有一个实际的异步点( Task.Delay ),调用线程返回到 Main ,然后在任务上同步阻止。一秒钟后, Task.Delay 任务完成,该方法的其余部分在另一个 ThreadPool 线程上执行。

Here we have an actual asynchronous point (Task.Delay) the calling thread returns to Main and then blocks synchronously on the task. After a second the Task.Delay task is completed and the rest of the method is executed on a different ThreadPool thread.

如果不是 Task.Delay ,我们会使用 Thread.Sleep ,那么它们都将在同一调用线程上运行。

If instead of Task.Delay we would have used Thread.Sleep then it will all run on the same calling thread.