Async 和 Await 实际上在做什么?

2025-06-07

Async 和 Await 实际上在做什么?

您是否曾经编写过一个函数,它调用了另一个恰好是异步的函数?Intellisense 会提示被调用的函数未被等待。您是怎么做的?添加关键字 await,瞧!您的问题解决了。

但是你的代码在做什么?

没时间琢磨这些,赶紧创建拉取请求,等着领导来深究,祈祷他们不会要求你解释 的用法,await或者为什么要把函数标记为async。你不能让他们觉得你不知道自己在做什么!

它不是什么

异步编程并非并行编程。它并非意味着“线程 A 执行 X”然后“线程 B 执行 Z”。它意味着你当前正在使用的“线程”将执行所有任务,但顺序会优化性能。一个常见的例子是做早餐。假设你正在煎鸡蛋和吐司。第一步是加热锅。在锅加热的同时,将鸡蛋从冰箱中取出,将面包从食品柜中取出。现在锅热了,打散鸡蛋开始煎。煎鸡蛋的同时,将面包放入烤面包机。鸡蛋煎好了。装盘。吐司也做好了。装盘。大功告成。虽然只需要一个人,使用一个线程,但任务的完成方式是两种食物同时烹饪。

异步

Asyncawait允许在方法中使用关键字。标有 async 关键字的方法会像其他函数一样执行,直到执行到包含该await关键字的行为止。

等待

Await提供了一种非阻塞的方式来启动任务。如何实现?通过方法控制流。当调用下载文件的任务时,线程不会等待任务完成。它会将控制权交给调用方法,继续工作,直到需要文件下载的结果。await关键字指示方法在何时被暂停,如果任务尚未完成,则控制权已移交给调用函数。

如果等待的async方法已经完成,它将返回存储在对象中的结果Task

以下是控制流程的有用图表:
异步控制流

任务异步编程(TAP)模型

C# 使用任务异步编程 (TAP) 模型来提供对异步代码的抽象。这使我们能够在执行异步任务时以同步方式读写代码。编译器会完成所有工作,确定何时需要暂停方法以及它们的执行顺序。如果没有语言支持,完成这项工作将需要开发人员编写大量代码,而这会使正在执行的业务逻辑的意图变得复杂。

TAP 模型本质上利用Task对象来保存异步方法的结果、进度和其他信息。您可以将异步方法的结果存储到 类型的对象中Task。当需要结果时,您可以使用awaitTask对象来检索异步方法的结果。

public async Task cookBreakfast() {
    // Start toasting the bread and let me hold onto an object
    // that I can use to retrieve the result later
    Task toastTask = toastBreadAsync();

    Console.log("Frying eggs");

    // I need the result of ToastBreadAsync() now
    await toastTask;
    Console.WriteLine("toast is ready");
}

public async Task toastBreadAsync(){
    Console.WriteLine("Starting on toast");
    await someToastyThings();
    Console.WriteLine("Done Toasting!");
}
Enter fullscreen mode Exit fullscreen mode

上述代码执行的结果将如下所示:

"Starting on toast"
"Frying eggs"
"Done Toasting!"
"toast is ready"
Enter fullscreen mode Exit fullscreen mode

让我们来看一下。

  1. 调用 cookBreakfast()。
  2. 调用 toastBreadAsync()
  3. 打印“Starting on toast”
  4. someToastyThings() 被调用并等待。将控制权移交给 cookBreakfast()
  5. toastBreadAsync() 将其任务存储到 toastTask 中
  6. 印有“煎鸡蛋”字样
  7. 正在等待 toastTask。控制权回到 someToastyThings();完成了吗?假设完成了。
  8. 打印“烘烤完成”
  9. 控制权回归,做早餐
  10. 打印“吐司已准备好”

同步与异步

指出构建异步应用程序与同步应用程序之间的差异非常重要,特别是使用 TAP 模型。

  • 您会注意到,同步方法在完成时会返回一个值。然而,异步方法会Task立即返回一个值,并在最终完成时将结果存储在 中Task
  • 接下来是控制流。当等待某个方法并且该方法的结果尚未可用时,控制权将移交给调用函数。另一方面,使用同步编程,控制权将继续执行下一行。

进一步阅读

我并非天生就了解这些知识。这里有一些非常好的资源,可以帮助我深入了解这个主题。

我希望这篇文章能帮助您初步了解 dotnet 中的异步编程。关于这个主题,还有很多更有趣的东西可以实现,但第一步是了解应用程序中正在发生的事情。

充满信心地继续你的 PR!

文章来源:https://dev.to/sumaiyaasif/async-and-await-and-what-is-it-actually-doing-34l
PREV
如何使用 Node.js 和 Heroku 创建 Twitter 机器人目录 the-datascience-bot
NEXT
如何设置 NGINX Docker 反向代理?