是否 any 场景写作方法如下:
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();
}
会有意义吗?
Why use return await construct when you can directly return Task<T> from the inner DoAnotherThingAsync() invocation?
我在很多地方看到 return await
的代码,我想我应该错过一些东西 . 但据我了解,在这种情况下不使用async / await关键字并直接返回Task将在功能上等效 . 为什么要增加额外的 await
图层的额外开销?
6 回答
当正常方法中的
return
和async
方法中的return await
表现不同时有一个偷偷摸摸的情况:当与using
(或更一般地,try
块中的任何return await
)组合时 .考虑这两个版本的方法:
一旦
DoAnotherThingAsync()
方法返回,第一个方法就会Dispose()
Foo
对象,这可能早在实际完成之前 . 这意味着第一个版本可能是错误的(因为Foo
过早地处理),而第二个版本可以正常工作 .如果您不需要
async
(即,您可以直接返回Task
),则不要使用async
.在某些情况下
return await
很有用,就像你有两个异步操作一样:有关
async
表现的更多信息,请参阅Stephen Toub关于该主题的MSDN article和video .Update: 我写了一篇更详细的blog post .
您想要这样做的唯一原因是,如果在早期代码中有其他
await
,或者如果您在返回之前以某种方式操纵结果 . 另一种可能发生的方式是通过改变异常处理方式的try/catch
. 如果你不是正确的话,没有理由增加制作方法async
的开销 .您可能需要等待结果的另一个案例是:
在这种情况下,
GetIFooAsync()
必须等待GetFooAsync
的结果,因为T
的类型在两种方法之间是不同的,并且Task<Foo>
不能直接分配给Task<IFoo>
. 但是如果你等待结果,它就会变成Foo
,它可以直接分配给IFoo
. 然后async方法只是重新打包Task<IFoo>
中的结果然后离开你 .使异常简单的“thunk”方法异步在内存中创建异步状态机,而非异步状态机则不在内存中 . 虽然这通常指向人们使用非异步版本,因为它更有效(这是真的)它也意味着在挂起的情况下,你没有证据表明该方法涉及“返回/继续堆栈”这有时会让人更难理解这个问题 .
所以是的,当perf不是关键的(通常不是)时,我会在所有这些thunk方法上抛出异步,这样我就可以使用异步状态机帮助我以后诊断挂起,并帮助确保如果那些thunk方法随着时间的推移而发展,他们肯定会返回故障任务而不是抛出 .
这也让我感到困惑,我觉得以前的答案忽略了你的实际问题:
好吧,有时你真的想要一个
Task<SomeType>
,但大多数时候你真的想要一个SomeType
的实例,也就是来自任务的结果 .从您的代码:
不熟悉语法的人(例如我)可能认为此方法应该返回
Task<SomeResult>
,但由于它标有async
,这意味着它的实际返回类型是SomeResult
. 如果你只是使用return foo.DoAnotherThingAsync()
,那么你就可以编译了.1448395_ . 正确的方法是返回任务的结果,所以return await
.