C#中“return await”的目的是什么?

没有这样写的方法:

public async Task<SomeResult> DoSomethingAsync() { // Some synchronous code might or might not be here... // return await DoAnotherThingAsync(); } 

而不是这个:

 public Task<SomeResult> DoSomethingAsync() { // Some synchronous code might or might not be here... // return DoAnotherThingAsync(); } 

会有道理吗?

为什么使用return await构造函数可以直接从内部的DoAnotherThingAsync()调用中返回Task<T>

我看到在这么多地方有return await代码,我想我应该错过了一些东西。 但据我所知,在这种情况下不使用async / await关键字,直接返回任务在function上是等价的。 为什么添加额外的await层的额外开销?

当在正常方法中return await时有一个偷偷摸摸的情况,在async方法中return await行为有所不同:当与using (或更一般地,在try块中的任何return await )结合时。

考虑这两个方法的版本:

 Task<SomeResult> DoSomethingAsync() { using (var foo = new Foo()) { return foo.DoAnotherThingAsync(); } } async Task<SomeResult> DoSomethingAsync() { using (var foo = new Foo()) { return await foo.DoAnotherThingAsync(); } } 

第一种方法会在DoAnotherThingAsync()方法返回时立即Dispose() Foo对象,这很可能早在它实际完成之前。 这意味着第一个版本可能是越野车(因为Foo处置得太快),而第二个版本可以正常工作。

如果你不需要async (即,你可以直接返回Task ),那么不要使用async

在某些情况下, return await是有用的,就像有两个asynchronous操作一样:

 var intermediate = await FirstAsync(); return await SecondAwait(intermediate); 

有关async性能的更多信息,请参阅Stephen Toub关于该主题的MSDN文章和video 。

更新:我写了一篇博客文章 ,更详细地介绍。

你想要这样做的唯一原因是,如果在前面的代码中还有其他的await ,或者在返回之前以某种方式操纵结果。 另一种可能发生的方式是通过try/catch来改变如何处理exception。 如果你没有这样做,那么你是对的,没有理由添加使方法async的开销。

另外一个你可能需要等待的结果是这样的:

 async Task<IFoo> GetIFooAsync() { return await GetFooAsync(); } async Task<Foo> GetFooAsync() { var foo = await CreateFooAsync(); await foo.InitializeAsync(); return foo; } 

在这种情况下, GetIFooAsync()必须等待GetFooAsync的结果,因为T的types在两个方法之间不同, Task<Foo>不能直接分配给Task<IFoo> 。 但是如果你等待结果,它就变成了直接分配给IFoo Foo 。 然后,asynchronous方法只是重新包装Task<IFoo>内的结果,并离开你去。

制作其他简单的“thunk”方法async会在内存中创build一个asynchronous状态机,而非async状态机则不会。 虽然这经常可以指出人们使用非asynchronous版本,因为它更有效率(这是真实的),这也意味着在挂起的情况下,没有证据表明该方法涉及“返回/连续堆栈”这有时使得更难理解挂起。

所以是的,当perf不重要时(通常不会),我会对所有这些thunk方法进行asynchronous处理,以便我有asynchronous状态机来帮助我稍后诊断挂起,还有助于确保如果那些thunk方法随着时间的推移而变化,他们一定会返回错误的任务而不是抛出。

这也混淆了我,我觉得以前的答案忽略了你的实际问题:

为什么使用return await构造函数可以直接从内部的DoAnotherThingAsync()调用返回Task?

那么有时你真的想要一个Task<SomeType> ,但是大多数时候你实际上需要一个SomeType的实例,也就是任务的结果。

从你的代码:

 async Task<SomeResult> DoSomethingAsync() { using (var foo = new Foo()) { return await foo.DoAnotherThingAsync(); } } 

一个不熟悉语法的人(例如我)可能会认为这个方法应该返回一个Task<SomeResult> ,但是由于它被标记为async ,这意味着它的实际返回types是SomeResult 。 如果你只是使用return foo.DoAnotherThingAsync() ,你会返回一个任务,不会编译。 正确的方法是返回任务的结果,所以return await