TX_*_*TX_ 219 .net c# async-await .net-4.5
有没有像这样编写方法的场景:
public async Task<SomeResult> DoSomethingAsync()
{
// Some synchronous code might or might not be here... //
return await DoAnotherThingAsync();
}
Run Code Online (Sandbox Code Playgroud)
而不是这个:
public Task<SomeResult> DoSomethingAsync()
{
// Some synchronous code might or might not be here... //
return DoAnotherThingAsync();
}
Run Code Online (Sandbox Code Playgroud)
会有意义吗?
为什么return await
在可以直接Task<T>
从内部DoAnotherThingAsync()
调用返回时使用构造?
我return await
在很多地方看到代码,我想我应该错过一些东西.但据我了解,在这种情况下不使用async/await关键字并直接返回Task将在功能上等效.为什么要增加附加await
层的额外开销?
svi*_*ick 172
有当一个欺骗性的情况下return
在正常的方法和return await
在async
方法不同的行为:当与组合using
(或,更一般地,任何return await
在try
块).
考虑这两个版本的方法:
Task<SomeResult> DoSomethingAsync()
{
using (var foo = new Foo())
{
return foo.DoAnotherThingAsync();
}
}
async Task<SomeResult> DoSomethingAsync()
{
using (var foo = new Foo())
{
return await foo.DoAnotherThingAsync();
}
}
Run Code Online (Sandbox Code Playgroud)
方法返回时,第一个方法将Dispose()
是Foo
对象DoAnotherThingAsync()
,它可能在实际完成之前很久.这意味着第一个版本可能是错误的(因为Foo
太快了),而第二个版本可以正常工作.
Ste*_*ary 85
如果您不需要async
(即,您可以Task
直接退货),那么请不要使用async
.
在某些情况下return await
,如果您要执行两个异步操作,则有用:
var intermediate = await FirstAsync();
return await SecondAwait(intermediate);
Run Code Online (Sandbox Code Playgroud)
有关async
性能的更多信息,请参阅Stephen Toub 关于该主题的MSDN文章和视频.
Ser*_*rvy 23
你想要这样做的唯一原因是,如果await
在早期的代码中有其他一些,或者你在返回它之前以某种方式操纵结果.可能发生的另一种方式是通过try/catch
改变异常处理方式.如果你没有做任何事情,那么你是对的,没有理由增加制作方法的开销async
.
And*_*ott 16
您可能需要等待结果的另一个案例是:
async Task<IFoo> GetIFooAsync()
{
return await GetFooAsync();
}
async Task<Foo> GetFooAsync()
{
var foo = await CreateFooAsync();
await foo.InitializeAsync();
return foo;
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,GetIFooAsync()
必须等待结果,GetFooAsync
因为T
两种方法之间的类型不同,并且Task<Foo>
不能直接赋值Task<IFoo>
.但是,如果你等待的结果,它只是成为Foo
这是直接分配给IFoo
.然后异步方法只是重新打包内部Task<IFoo>
和远离你的结果.
使原本简单的“ thunk”方法异步进行,则会在内存中创建一个异步状态机,而非异步状态机则不会。尽管这样做通常可以使人们指出使用非异步版本,因为它效率更高(的确如此),这也意味着在挂起的情况下,您没有证据表明该方法已包含在“返回/继续堆栈”中这有时会使理解挂起变得更加困难。
所以是的,当性能不是很关键(通常不是)时,我将对所有这些重击方法都进行异步处理,以便我拥有异步状态机来帮助我以后诊断挂起,并帮助确保是否重击方法随着时间的推移而发展,他们将确保返回错误的任务,而不是抛出错误。
这也让我感到困惑,我觉得之前的答案忽略了您的实际问题:
当您可以直接从内部 DoAnotherThingAsync() 调用返回 Task 时,为什么要使用 return await 构造?
好吧,有时您实际上想要的是Task<SomeType>
,但大多数时候您实际上想要的是 的实例SomeType
,即任务的结果。
从您的代码:
async Task<SomeResult> DoSomethingAsync()
{
using (var foo = new Foo())
{
return await foo.DoAnotherThingAsync();
}
}
Run Code Online (Sandbox Code Playgroud)
不熟悉语法的人(例如我)可能认为这个方法应该返回 a Task<SomeResult>
,但由于它被标记为async
,这意味着它的实际返回类型是SomeResult
。如果您只是使用return foo.DoAnotherThingAsync()
,您将返回一个无法编译的任务。正确的方法是返回任务的结果,所以return await
.
如果不使用return wait,则可能在调试时或在异常日志中打印堆栈跟踪时破坏堆栈跟踪。
当您返回任务时,该方法已实现其目的,并且不在调用堆栈中。使用时return await
,将其保留在调用堆栈中。
例如:
使用await时调用堆栈:A从B等待任务=> B从C等待任务
不使用等待时调用堆栈:A正在等待C返回的B任务。
归档时间: |
|
查看次数: |
33199 次 |
最近记录: |