【问题标题】:Task Await Call misunderstanding任务等待呼叫误解
【发布时间】:2018-04-27 23:17:30
【问题描述】:

谁能给我解释一下这是怎么回事?这是我在另一篇帖子中询问的答案 (Does await new Task(async () => Actually halt execution until finished?),但我并不真正理解部分评论...

异步等待——await——等待任务完成。那是 为什么它被称为“等待”。

它是异步的,因为如果任务未完成则等待 返回给调用者并在这个线程上做其他工作,直到 任务完成,此时等待之后的工作是 计划执行。

确保您了解 await 是任务的运算符。它不是 关于调用的调用约定。任何等待类型的表达式都可以是 等待;不要落入相信 await 会打电话的陷阱 异步。被调用的方法已经是异步的;那个任务 返回的是等待的东西。

它如何“等待任务完成”同时又“返回调用者并做其他工作”?

谢谢!

跟进:

我已经看到了响应,那么在下面的伪代码示例中应该发生什么?哪些任务会按顺序实际发生?

await new Task(async () =>
{
    //Do stuff 1
    Thread.Sleep(10000);
}

EventLog.Write("Do Stuff 2");

await new Task(async () =>
{
    //Do stuff 3
    Thread.Sleep(10000);
}

“Do Stuff 1”会执行,然后等待,然后“Do Stuff 2”会发生,然后“Do Stuff 3”会发生吗?还是会先执行“Do Stuff 1”,然后立即执行“Do Stuff 2”,然后再执行“Do Stuff 3”?

【问题讨论】:

  • 它“逻辑上”等待,这意味着下一行只会在任务完成后执行。
  • 方法被分成几部分。在遇到await 之前和之后。 await 之前的所有代码都是同步执行的。 await 之后的所有代码都安排为 Continuation。所以它立即返回给调用者,然后当await 完成时,其余代码被调用,在ThreadPool 线程或捕获的SynchronizationContext
  • 应该注意的是,在windows GUI应用程序继续将在消息循环处于空闲状态后执行。
  • 我已经根据你的例子更新了我的答案。

标签: c# async-await


【解决方案1】:

并非所有工作都需要 CPU 或线程。

假设您正在向 Web 服务发出 HTTP 请求。或者从磁盘或网络位置流式传输文件。在这些情况下,请求由另一个硬件组件(例如网络适配器或磁盘控制器)处理。

如果网络存在延迟,并且需要很长时间才能得到响应,该怎么办?你可以坐在那里阻塞,等待响应。或者你可以利用这段时间做其他事情。

这就是asyncawait 真正有用的地方。当您await 一个正在执行 I/O 的方法(例如磁盘或网络)时,它基本上是在说“请在此任务完成时告诉我”。然后您将返回调用者,以便您可以做其他工作(可能是 CPU 限制,也可能是 I/O 限制)。

当您等待的任务完成后,await 语句之后的其余方法将运行。这称为延续 - 本地状态在 await 语句时被捕获,它只是从中断的地方继续。

我听说过的一个很好的比喻是做早餐。假设您正在喝一杯咖啡和吐司。烧开水壶需要 2 分钟。你可以站在那里等水壶烧开,然后煮咖啡和烤面包。或者你可以开始煮沸的任务,去烤面包,然后当你听到水壶的啸叫声时,你的“煮咖啡”任务从中断的地方继续。哪个效率更高?


在您的示例中,您将按以下顺序获得以下信息:

  • 等待 10 秒(执行 1)
  • 写入事件日志(做事 2)
  • 等待 10 秒(做 3 件事)

在您等待的Task 完成之前,我们不会在每个await 呼叫之后继续。在这种情况下,您正在等待 async Task,因此它实际上是 Task<Task>(因为异步委托本身使用 Task)。但我认为外部await 会同时解开Task,并且当最外部的Task 完成时,会安排继续。

【讨论】:

  • 实际上并不是一个答案,OP 询问在技术上等待如何在低级别 - 线程、消息循环中发生,您的解释只是关于异步原理。
  • @Fabio - 根据后续示例,我认为 OP 并没有问这个问题。
  • 好的。所以它会等到每次调用 await 时任务完成。谢谢!
猜你喜欢
  • 2018-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多