试图理解新的异步/等待模式,我有一个问题,我找不到答案,即如果我打算用异步装饰我的方法,如果我打算从其他异步函数调用这些方法,或者只需在适当的地方返回Task
?
换句话说,这些A,B或C类中哪一个最好,为什么?
class A<T>
{
public async Task<T> foo1() //Should be consumed
{
return await foo2();
}
public async Task<T> foo2() //Could be consumed
{
return await foo3();
}
private async Task<T> foo3() //Private
{
return await Task.Run(...);
}
}
class B<T>
{
public async Task<T> foo1() //Should be consumed
{
return await foo2();
}
public async Task<T> foo2() //Could be consumed
{
return await foo3();
}
private Task<T> foo3() //Private
{
return Task.Run(...);
}
}
class C<T>
{
public async Task<T> foo1() //Should be consumed
{
return await foo2();
}
public Task<T> foo2() //Could be consumed
{
return foo3();
}
private Task<T> foo3() //Private
{
return Task.Run(...);
}
}
过度设计方法似乎多余,所以我自然倾向于C
,但同时使用Task<T>
感觉有点尴尬,除非您使用await
关键字。
答案 0 :(得分:9)
两个版本的工作效率相同,唯一的区别是当你在这里使用await
时,会受到一些性能损失(因为必须设置状态机并且最有可能使用延续)。 / p>
因此,它取决于权衡:您是否希望您的方法更有效,但代价是可读性稍差?或者你愿意为了可读性而牺牲性能吗?
通常情况下,我会建议您首先考虑可读性,如果分析告诉您它值得,则只关注性能。但在这种情况下,我认为可读性的增加很小,所以我可能不会使用await
。
另请注意,您的课程C
仍然不够远:foo1()
也不需要await
。
答案 1 :(得分:2)
签名中的async
允许编译器创建所包含代码的状态机重写,这是在一般情况下实现await
语义所必需的。
您的示例正是您不需要重写的特殊情况:异步操作是方法中发生的最后一件事。这种方法已经可以在.NET4.0
中有效。当您不需要时,这种兼容性可能是避免async
的一个原因。