【问题标题】:Async and await: multiple await expressions异步和等待:多个等待表达式
【发布时间】:2015-05-22 12:10:30
【问题描述】:

我有点难以理解如何使用 async 和 await 工作。

我了解,当异步方法遇到 await 表达式时,该方法会立即返回,并且在将来的某个时间点,await 表达式会返回并且该方法会继续执行。

那么,我不明白的是,当异步方法包含多个等待表达式时会发生什么?当执行到第二个 await 表达式时,由于在第一个 await 表达式被命中后方法已经返回,那么围绕第二个 await 表达式执行会发生什么?

我目前正在阅读两本关于 async 和 await 的书,但我的黑暗思想都没有被这本书照亮!

【问题讨论】:

    标签: c# asynchronous async-await


    【解决方案1】:

    回想一下,对于编译器遇到的每次等待,它都会重写方法的其余部分作为延续,这可能会有所帮助。所以 2 次等待将导致 2 次(嵌套)延续,大致相当于(尽管过于简化):

    FirstAsyncThing().ContinueWith(x => {
        SecondAsyncThing().ContinueWith(y => {
            // etc.
        });
    });
    

    所以就像第一个 await 立即将控制权返回给方法的调用者一样,第二个 await 将控制权返回给第一个 continuation 的调用者,这是原始方法的第一部分。

    【讨论】:

      【解决方案2】:

      我了解,当异步方法遇到 await 表达式时,该方法会立即返回,并且在将来的某个时间点,await 表达式会返回并且该方法会继续执行。

      是的,如果等待还没有完成。

      当执行到第二个 await 表达式时,由于在第一个 await 表达式被命中后方法已经返回,那么围绕第二个 await 表达式执行会发生什么?

      它将控制权返回给执行延续的任何内容,这取决于上下文。在 UI 线程中的 WinForms 应用程序中,它只是事件循环。在线程池线程中,它只是线程池调度程序。

      机会是任何所谓的延续真的根本不关心它 - 它只是“在上下文中执行的东西”。它可能会继续执行下一步需要做的任何事情(或等到有更多工作)。

      重要的一点是,到目前为止,第一个调用者拥有适当的TaskTask<T>,这样他们就可以知道整个异步方法何时完成。

      【讨论】:

      • 答案不是很简单:与第一个等待相同。即该方法也将在第二点立即返回,除非已经完成,并且在将来的某个点第二个等待表达式返回并且该方法继续再次执行。这发生在方法中可能按顺序发生的所有等待中。
      • @PhilipStuyck:关键是 OP 对方法返回的第二个调用者 感到困惑(我相信)。
      • 那么当第一个awaitable正在执行时,代码返回完成调用者的代码?而在第二个等待期间,控制权返回到 UI 线程或线程池调度程序?
      • @serlingpa:差不多,是的。 (不过,我不认为它是“在 awaitable 执行时”——只是 awaitable 尚未完成。对于 Task.Delay 之类的事情,它实际上并没有做任何事情——它只是直到之后才完成延迟。)
      猜你喜欢
      • 2016-07-07
      • 2016-03-25
      • 2017-10-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多