我读过很多关于async/await
的内容,但我仍然不了解以下情况。
我的问题是,我应该实现我的"包装" DoSomething()
中的方法或DoSomethingAsync()
中的方法。
那么更好(以及为什么):我在包装器方法中使用await
还是直接返回任务?
public static async void Main()
{
await DoSomething();
await DoSomethingAsync();
}
private static Task DoSomething()
{
return MyLibrary.DoSomethingAsync();
}
private static async Task DoSomethingAsync()
{
await MyLibrary.DoSomethingAsync().ConfigureAwait(false);
}
public class MyLibrary
{
public static async Task DoSomethingAsync()
{
// Here is some I/O
}
}
答案 0 :(得分:8)
Async / Await仍然相对较新,但有一些很好的做法可以帮助澄清API。基础是:
async
的方法意味着以后期待await
async
为您隐式创建Task
。await
就像一个书签。应用程序将继续使用await关键字。await
任何不是IAwaitable
的东西(最常见的是Task
)(citation)在同时存在异步调用和同步调用的应用程序中,我们采用了命名约定:
async
调用返回Task
或Task<T>
,并将Async
附加到名称的末尾。通常,有两种方法可以做同样的事情,但一种是同步的,另一种不是。你可以用两种不同的方式实现它,也可以用另一种方式包装一种方式。这实际上取决于您的需求以及为您提供响应更快的应用程序。
在上面的示例中,处理异步和普通方法调用的正确方法是MyLibrary
公开两种方法。这个例子是这样的:
public static class MyLibrary
{
public static void DoSomething()
{
// do some work
}
public static async Task DoSomethingAsync()
{
// do similar work but use async API,
// can also simply call DoSomething().
}
}
// In another part of code would be called like this:
public static async Task BiggerMethod()
{
MyLibrary.DoSomething();
await MyLibrary.DoSomethingAsync();
}
您要避免的是使用常规方法包装async
方法。只要您直接使用Task
,就会失去async
和await
的所有好处,并且会引入代码可能陷入僵局的位置。
答案 1 :(得分:4)
Berin的答案很好,但未明确解决您问题中的特定情况,即以下示例:
1:直接返回任务
private static Task DoSomething()
{
return MyLibrary.DoSomethingAsync();
}
2:等待任务并返回结果
private static async Task DoSomethingAsync()
{
await MyLibrary.DoSomethingAsync().ConfigureAwait(false);
}
在这种情况下,直接返回Task
和等待Task
并返回响应之间的唯一区别是 - 在后一种情况下 - 必须由框架创建状态机来管理等待Task
的方法的开始,暂停和继续。这会产生一些性能开销。
一般来说,如果你可以返回一个Task
并允许它等待更高,你应该。然而,在大多数(但肯定不是全部)真实案例中,这将是不可能的,因为您将希望在返回之前执行某些结果处理(这正是async / await帮助您实现的目标)。 / p>
答案 2 :(得分:0)
单线的情况没有区别。
但是在at least two-async-liners
的情况下,例如:
public static async void Main()
{
await DoSomething();
await DoSomethingAsync();
}
private static Task DoSomethingTwice()
{
var do1 = MyLibrary.DoSomethingAsync();
// when you await DoSomethingTwice, next line's reached
// when do1 task may not be completed
var do2 = MyLibrary.DoSomethingAsync();
// return what???
// how to combine them?
// okay, you can do that
return Task.WhenAll(do1, do2)
}
private static async Task DoSomethingTwiceAsync()
{
await MyLibrary.DoSomethingAsync().ConfigureAwait(false);
// when you await DoSomethingTwiceAsync, next line's reached
// when prev-line task is completed
await MyLibrary.DoSomethingAsync().ConfigureAwait(false);
}
public class MyLibrary
{
public static async Task DoSomethingAsync()
{
// Here is some I/O
}
}
要点:
doAsync1()
- &gt; doAsync2()
- &gt; doAsync3()
,即。每一个下一个和平都需要完成前一个和平的结果,那么你应该等待每个电话:
async Task DoAsync()
{
await doAsync1();
await doAsync2();
await doAsync3();
}
non-async
方法中使用等待。因此,您无法以Task DoSomething()
样式执行,只能async Task DoSomethingAsync()
。