当我"等待"一个"异步"方法时它会变成同步吗?

mdl*_*ars 22 c# asynchronous async-await

所以这是场景:

static async void Main(string[] args) 
{
    await AnAsyncMethod();
}

private static async task<bool> AnAsyncMethod()
{
    var x = await someAsyncMethod();
    var y = await someOtherAsyncMethod();

    return x == y;
}
Run Code Online (Sandbox Code Playgroud)

"someAsyncMethod"和"someOtherAsyncMethod"是否同步运行,因为我们正在使用await,或者它们是否按照执行顺序异步运行?

UPDATE

鉴于以下答案说明等待的异步方法将按顺序运行,如果我们只是停止执行并等待那些方法的返回值,那么首先使这些方法调用异步的目的是什么?我曾经看过过去的原生应用程序使用await/async作为释放UI线程的方法,但是有没有其他原因可以解释为什么这个设计是可取的呢?

dca*_*tro 28

它们是异步运行的,但是顺序运行.someOtherAsyncMethodsomeAsyncMethod完成之前不会被调用.

如果要并行运行它们,您有几种选择

var taskA = MethodA();
var taskB = MethodB();

var a = await taskA;
var b = await taskB;

// or

var results = await Task.WhenAll(MethodA(), MethodB());
Run Code Online (Sandbox Code Playgroud)

后续问题:

我曾经看过过去的原生应用程序使用await/async作为释放UI线程的方法,但是有没有其他原因可以解释为什么这个设计是可取的呢?

在ASP.NET应用程序中,您将需要使用它来允许当前线程返回到线程池并在MethodA/ MethodB正在运行时提供其他传入请求- 如果这些方法正在执行真正的异步I/O. 这基本上是你在ASP.NET应用程序中执行此操作的唯一原因.

您可能还想阅读Stephen Cleary的:

  • 而且不仅仅是在ASP.NET中 - 在任何多用户服务器应用程序中,您都可以从保持低线程数中受益.每个线程意味着不可忽略的内存和CPU使用 - 如果你有4000个线程,你就会在默认的线程堆栈上丢失4 GiB的内存(希望至少是非提交的).而且,由于你只拥有与拥有CPU内核一样多的线程,所以给予或接受,这是完全不必要的浪费.在32位应用程序中尤其如此,即使*虚拟*内存的数量也是有限的. (4认同)
  • 请注意,您不能在相同的上下文中使用Task.WhenAll与多个EF调用.那个人以前肯定咬了我. (2认同)
  • @Biscuits选项1将启动两个任务,*然后*等待它们.你是否等待'a`然后'b`,或'b`然后'a`并不重要.重要的是你在等待*之前启动***. (2认同)
  • @Biscuits混淆是可以理解的,并且源于这些表达式不是[引用透明]的事实(http://programmers.stackexchange.com/a/254308/1013080).也就是说,用`MethodA()`替换`taskA`会改变程序的*含义*. (2认同)