在单个异步方法中有多个等待的目的

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在单个异步方法中有多个等待的目的相关的知识,希望对你有一定的参考价值。

如果您有异步功能:

public async Task DoWork()
{
    await DoSomeWorkAsync();
    await DoSomeMoreWorkAsync();
}

现在第一个await阻止了阻塞调用上下文的方法,因此很有用。

但是在DoSomeWorkAsync完成之后,该方法无论如何都在不同的上下文中运行,因为在编译器中它被转换为类似Task.ContinueWith(await DoSomeMoreWorkAsync())的东西。

他们等待DoSomeMoreWorkAsync /运行异步的任何目的是什么?有什么缺点吗?如果它存在,我应该使用非同步版本的DoSomeMoreWorkAsync吗?

即。这会不会有任何不利之处:

public async Task DoWork()
{
    await DoSomeWorkAsync();
    DoSomeMoreWork();
}

编辑:这与Multiple Awaits in a single method不是同一个问题。那询问会发生什么。我在问这件事有什么好处。

答案

您似乎在考虑避免阻塞调用方是异步方法的唯一目的,但事实并非如此。异步方法通常是异步的,因为它们在某些时候执行异步IO,例如处理文件,数据库,Web请求等(或调用执行此操作的其他异步方法)。

当真正的异步IO正在进行中时,应用程序中的任何线程都没有忙着等待它完成(好吧,有线程,但它是整个应用程序的一个,而不是每个特定的IO任务)。

这意味着即使IF await DoSomeMoreWorkAsync在某个线程池线程上执行 - 在某些时候它将达到异步IO - 此线程池线程将被释放并可用于更有用的工作。

另一方面,如果您将使用同步版本(DoSomeMoreWork) - 它将在整个持续时间内阻止当前线程池线程,包括IO,因此该线程将无法用于有用的工作。

尽可能释放线程在使用它们的应用程序中非常重要,例如Web应用程序。

除上述内容外,此声明

但是在DoSomeWorkAsync完成之后,该方法无论如何都在不同的上下文中运行

并非总是如此。例如,在UI应用程序中,如果从UI线程调用DoWork,则还将在UI线程上执行continuation(await DoSomeMoreWorkAsync())。这意味着如果用同步版本替换它 - UI线程将在其持续时间内冻结。

另一答案

那么等待DoSomeMoreWorkAsync有什么目的吗?

好吧,如果它是异步的,那么你绝对想要等待它,所以你的DoWork方法在完成“更多工作”之前没有完成。如果它是异步的,并且你没有等待它,它本质上是火,忘记哪个很少你想要的。

那么运行它是否有任何目的异步?

这取决于功能。您不要使方法异步,因为您要将它们称为异步。方法是异步的,因为它们执行异步任务。

如果该方法正在进行纯粹的CPU绑定工作,无论如何都不会异步运行,那么就没有理由让它异步,不。实际上,让它保持同步,以便与调用者清楚地通信,即没有异步进程正在进行。

但是,如果它是从异步中受益的东西,例如因为它执行异步网络或I / O调用,所以它可能应该是异步的。然后你也应该等待它。

有什么缺点吗?

总有缺点。运行异步代码比运行同步代码更昂贵,因为生成并调用了很多开销(我们在编写异步代码时很幸运不需要处理)。但是,在查看真正的异步代码可以为您提供的优势时,这种开销并不重要。

所以你真的不应该用它来决定是否要异步。考虑一下该方法的作用以及它是如何做的,然后决定该进程是同步还是异步。

以上是关于在单个异步方法中有多个等待的目的的主要内容,如果未能解决你的问题,请参考以下文章

异步等待虚方法

Mdb 与 EJB 3.1 异步方法

js Promise 等待多个异步操作执行完再去做一些操作

在单个片段事务中添加多个返回堆栈条目

是否有在单个活动中处理多个片段的 Android 设计模式?

异步/等待不等待返回值