【问题标题】:Effects of using multiple awaits in the same method?在同一方法中使用多个等待的效果?
【发布时间】:2016-05-02 20:55:31
【问题描述】:

我有以下方法可以将更改提交到数据库(使用实体框架):

public async Task<int> CommitAsync(Info info)
{
    if (this.Database.Connection.State == ConnectionState.Closed)
        await this.Database.Connection.OpenAsync();

    await SetInfo(info);
    return await base.SaveChangesAsync();
}

上述方法可以安全使用吗,还是应该:

  1. 避免使用async-await,或
  2. 使用ContinueWith

【问题讨论】:

    标签: c# asynchronous async-await


    【解决方案1】:

    在同一个异步方法中拥有多个 await 表达式绝对没问题 - 否则这将是相对无用的功能。

    基本上,该方法将同步执行,直到它到达第一个await,其中涉及的等待对象尚未完成。然后它将返回给调用者,并为等待的对象设置了一个延续来执行其余的异步方法。如果稍后执行到达另一个 await 表达式,其中 awaitable 尚未完成,则在 that awaitable 上设置延续,等等。

    每次方法从等待中“恢复”时,它都会从中断处继续,使用相同的局部变量等。这是通过编译器代表您构建状态机来实现的。

    【讨论】:

    • 我的理解正确吗?如果我们有两个等待,第二个等待之后的代码只会继续第二个等待而不是第一个等待如果不是这种情况,那么第二个等待之后的代码将运行两次(首先,作为第一个的延续awaitable 和 second 作为第二个 awaitable 的延续。
    • @Rouftantical:是的,正如我所说的“它从停止的地方继续”。
    【解决方案2】:

    您的代码看起来很完美。它使您的呼叫者有机会在您等待的时候做一些有用的事情,而不是每个人都忙着等待一切都完成。

    使用 async-await 而不是 ContinueWith 的好处是您的代码看起来相当同步。很容易看出语句的执行顺序。 ContinueWith 也可以让你指定顺序,但是有点难看。

    如果线程进入异步过程,它会执行该过程,直到遇到等待。与其等到等待的过程完成,不如将控制权交还给您的调用者,后者可以继续执行下一条语句,直到遇到等待,将控制权交给他的调用者等。一旦每个人都在等待并且您的 OpenAsync 完成线程继续执行 OpenAsync 之后的语句,直到遇到另一个 await。

    stackoverflow 中的某个人(可惜失去了他的名字)曾经在 breakfast metaphor 中向我解释过异步等待过程。

    非常有用的介绍,Stephen Cleary about Async-await。让您还了解 async-await 如何防止 InvokeRequired 出现问题

    【讨论】:

    • 我认为早餐比喻是从 Eric Lippert 开始的。这是其中某些部分的链接。 i-programmer.info/professional-programmer/i-programmer/… 在过去几年左右的时间里,我一直像鹰一样关注 Skeet、Cleary 和 Lippert。一定要阅读一碗水果和动物笼子的比喻。
    猜你喜欢
    • 2012-11-18
    • 2022-01-01
    • 1970-01-01
    • 2013-08-29
    • 1970-01-01
    • 2013-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多