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

时间:2018-03-05 11:00:22

标签: c# asynchronous async-await

如果您有异步功能:

resource1

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

但是在public async Task DoWork() { await DoSomeWorkAsync(); await DoSomeMoreWorkAsync(); } 完成之后,该方法无论如何都在不同的上下文中运行,因为在编译器中它已被转换为类似DoSomeWorkAsync的内容。

等待Task.ContinueWith(await DoSomeMoreWorkAsync()) /运行异步的任何目的是什么?有什么缺点吗?如果存在,我应该使用DoSomeMoreWorkAsync的非异步版本吗?

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

DoSomeMoreWorkAsync

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

2 个答案:

答案 0 :(得分:7)

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

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

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

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

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

除了上述内容,本声明

  

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

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

答案 1 :(得分:3)

  

等等DoSomeMoreWorkAsync是否有任何目的?

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

  

那么运行异步是否有任何意义?

这取决于功能。你使方法异步,因为你想调用异步。方法是异步的,因为它们执行异步任务。

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

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

  

有任何缺点吗?

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

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