等待最后一个异步调用和返回它有区别吗? [复制]

Posted

技术标签:

【中文标题】等待最后一个异步调用和返回它有区别吗? [复制]【英文标题】:Is there a difference between awaiting the last async call and just returning it? [duplicate] 【发布时间】:2017-10-02 10:27:21 【问题描述】:

查看问题标题。

换句话说,给定一个方法

async Task FrobnicateAsync()  ... 

两者之间是否有任何(可能是细微的)区别

async Task FrobAndFrobnicateAsync()

    Frob();
    await FrobnicateAsync();

Task FrobAndFrobnicateAsync()

    Frob();
    return FrobnicateAsync();

【问题讨论】:

Bill Wagner 昨天写了一封blog post,其中包含一个潜在差异示例。 另见:***.com/questions/43536642 【参考方案1】:

我在eliding async 上有一篇博文。

由于您在await 之前有一个重要的Frob,我建议您保留 asyncawait。这种方法的好处是:

如果没有asyncFrob抛出异常,则直接抛出异常,这对消费者来说是令人惊讶的行为。即使Frob今天没有抛出异常,明年也可以这样做;因此await 的代码更易于维护。 如果没有async,那么Frob不存在与FrobnicateAsync相同的逻辑调用上下文中(假设它实际上是async);相反,它将与FrobAndFrobnicateAsync 的调用者存在于相同的逻辑调用上下文中。在大多数代码中,这不是问题。

另见What Is the Purpose of return await?

【讨论】:

【参考方案2】:

如果您字面意思显示了代码,那么您应该更喜欢return FrobnicateAsync() 版本 - 它避免了额外的状态机抽象层并且更高效。

如果您有其他东西 - 特别是任何finally(包括using)代码环绕return,那么您必须确保使用await 版本,这样finally 代码直到async 任务完成之后才会发生。

如有疑问,请使用async/await 版本。

好消息是:在它们之间切换不会影响签名(因此不是重大更改),因此您现在可以更有效地实现它,并更改为async/await if你发现你以后需要添加一个using块。

作为一个额外的想法:如果你通常期望它同步完成,你可以更微妙:

Task FrobAndFrobnicateAsync()

    async Task Awaited(Task t) => await t;
    Frob();
    var task = FrobnicateAsync();
    // in .NET vFuture there will be a task.IsCompletedSuccessfully
    return task.State == TaskState.RanToCompletion ? task : Awaited(task);    

这避免了状态机在不需要时

【讨论】:

我不确定我是否总是同意这一点——如果Frob 可能引发异常,那么使其异步有很大不同。请参阅 Stephen Cleary 的博文:blog.stephencleary.com/2016/12/eliding-async-await.html(在某些情况下我认为这很好,但在其他情况下则不然。) @JonSkeet 但您并没有吸收差异; caller 应该仍然是await-ing 或其他,所以他们会以通常的方式得到异常there 但这可能在他们的代码中完全不同。如果这是一个“调用者代码中的错误”异常(例如验证),那么我可以接受 - 如果它类似于 IOException,那么更改它被抛出的点感觉更像是一个重大变化。 @JonSkeet 啊,您的意思是在调用FrobnicateAsync 之前FrobAndFrobnicateAsync 内部的异常?同意:这绝对是一个区别;讨论哪个版本(如果有)更正确是一个非常复杂的对话。就个人而言,无论哪种方式,我都可以接受。 另一方面,在应用程序代码中,您更有可能了解您的调用者,并能够在必要时改变他们对异常的期望:)

以上是关于等待最后一个异步调用和返回它有区别吗? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

同步请求和异步请求区别

Python-异步编程

如果我不关心它的返回值,我应该等待一个“异步任务”函数吗? [复制]

并发编程

传递异步方法真的需要等待/异步模式吗? [复制]

异步/同步/阻塞/非阻塞