【问题标题】:Is this a correct diagram of how async-await works?这是 async-await 如何工作的正确图表吗?
【发布时间】:2016-12-11 20:31:00
【问题描述】:

我将尝试在async-await 上发表演讲,并且我正在创建一个流程图,试图显示可能的执行顺序。

我试图以段落为基础

异步方法的开头与其他方法一样执行 方法。也就是说,它会同步运行,直到遇到“等待”(或 抛出异常)。

“await”关键字是事情可以异步的地方。等待是 像一元运算符:它接受一个参数,一个可等待的( “awaitable”是一个异步操作)。等待检查 awaitable 看看它是否已经完成;如果等待的有 已经完成,然后该方法继续运行 (同步,就像常规方法一样)。

如果 “await” 看到 awaitable 没有完成,那么它就会行动 异步。它告诉等待运行的其余部分 方法完成后,然后从异步方法返回。

稍后,当 awaitable 完成时,它将执行剩余部分 的异步方法。如果您正在等待一个内置的可等待对象(例如 一个任务),那么异步方法的其余部分将在 在“等待”返回之前捕获的“上下文”。

来自http://blog.stephencleary.com/2012/02/async-and-await.html

【问题讨论】:

  • 顺便说一句,方法可以是同步的也可以是异步的,它仍然可以等待。
  • 您认为谈论您不太了解的事情是否明智?已经有大量关于此功能的错误信息和模糊思考;我不确定你想创造更多。
  • this diagram,来自here
  • 您的解释中的大部分模糊和挥手来自于对日程安排的含糊不清。例如,考虑一个 winforms 应用程序。有办法“完成所有独立工作”的想法应该让你深感怀疑;可以根据计时器滴答声或鼠标时刻或按键或按钮点击来安排该工作。如果工作将来自未来的按键,你怎么知道“所有工作”已经完成?如果你没有清楚地理解 Windows 是如何处理事件的,那么你就无法理解 winforms 中的 async。

标签: c# .net multithreading asynchronous async-await


【解决方案1】:

usr 的答案基本上是正确的,尽管我认为它在线程和任务之间进行了过于强烈的类比。任务不必像另一个线程。请记住,线程是工人,任务是工作。您可以在您的待办事项清单上列出一百件事,而无需雇用任何工人来完成它们。尽量不要将任务视为轻量级工作人员,因为它们不是。它们是需要完成的工作;工人做什么取决于交给你任务的代码。

您的图表开始时很好,但在“调用者是否完成了所有独立工作?”时偏离了轨道。调用者的延续是,好吧,不管它是什么。如果这种延续涉及到工作,它确实有效。其中一些工作可能是调度任务以在当前线程上运行。其中一些工作可能是保持 UI 响应。

另外,不要忘记调用者的线程可能会被终止,而任务的继续可能会被安排到另一个线程。

这里可以发生很多很多事情;如果不了解调用者到底在做什么以及调用者的线程上下文是什么,就不可能说出 await 返回后立即发生的事情。

【讨论】:

    【解决方案2】:

    这个

    含糊不清,似乎不正确。

    接下来会发生什么内部异步方法不依赖于调用者。该方法现在是一个独立的代理(如线程),它自己运行。它返回一个Task,它是它自己的句柄。调用者可以随心所欲地执行该任务(例如,等待它,等待它,...)。

    但如果调用者简单地删除了该任务,异步方法将继续运行。

    图片的“重新进入”部分发生在由等待的等待对象控制的时间。通常,这是一些外部事件,例如完成的 IO 或计时器。 async 方法现在恢复执行,不知道也不关心是谁重新激活了它。

    将每个异步方法视为一个独立的线程。每个await 逻辑上都是Thread.Join()

    【讨论】:

    • 虽然这个想法很容易理解,但实际上最好不要将任务——需要完成的事情——与线程——执行任务的工作人员混为一谈。等待是异步工作流中的连接点是一个重要的见解,但我认为过于强调线程作为考虑异步的默认机制。
    猜你喜欢
    • 2021-05-16
    • 2021-07-30
    • 2016-01-09
    • 1970-01-01
    • 2021-12-18
    • 2020-08-23
    • 1970-01-01
    • 2018-11-26
    相关资源
    最近更新 更多