C# 等待期间多个任务的控制流

C# 等待期间多个任务的控制流,c#,.net,asynchronous,async-await,C#,.net,Asynchronous,Async Await,当我有两个任务而我在等待一个任务时,我在等待过程中很难理解控制流。只使用了一个等待,因此没有帮助 我有以下代码: public async Task Loop(string name, int count) { for (int i = 0; i < count; i++) { Console.WriteLine("{0}: {1} Before", name, i); await Task.Delay(10); Consol

当我有两个任务而我在等待一个任务时,我在等待过程中很难理解控制流。只使用了一个等待,因此没有帮助

我有以下代码:

public async Task Loop(string name, int count)
{
    for (int i = 0; i < count; i++)
    {
        Console.WriteLine("{0}: {1} Before", name, i);
        await Task.Delay(10);
        Console.WriteLine("{0}: {1} After", name, i);
    }
    Console.WriteLine("{0} COMPLETE", name);
}

[TestMethod]
public async Task TwoLoopsWithSeparateAwait()
{
    var loopOne = Loop("ONE", 3);
    Console.WriteLine("After ONE Creation");
    var loopTwo = Loop("TWO", 3);
    Console.WriteLine("After TWO Creation, before ONE await");
    await loopOne;
    Console.WriteLine("After ONE await");
    await loopTwo;
    Console.WriteLine("After TWO await");
}
公共异步任务循环(字符串名称、整数计数)
{
for(int i=0;i
结果如下:

  • 1:0之前
  • 一次创作之后
  • 2:0之前
  • 在两次创造之后,在一次等待之前
  • 2:0之后
  • 2:1之前
  • 1:0之后
  • 一比一
  • 1:1之后
  • 1:2之前
  • 2:1之后
  • 2:2之前
  • 2:2之后
  • 两个完整的
  • 1:2之后
  • 完整的
  • 等待
  • 两天后等待
根据报告:

等待表达式不会阻塞正在其上执行的线程。相反,它使编译器将异步方法的其余部分注册为等待的任务的延续。控件然后返回给异步方法的调用方。当任务完成时,它调用它的continuation,异步方法的执行在它停止的地方继续

在等待loopOne之前,我知道会发生什么,但我认为只有loopOne会被执行(可能是同步的),它看起来更像是一个收益,保留可能继续的可能任务列表(我认为这符合“当任务完成时,它调用它的继续”)


在等待多个任务期间,控制流背后的逻辑是什么?

异步方法将同步执行,直到到达
await
。然后,它创建一个任务,该任务表示您正在等待的
async
操作以及其余代码,作为操作完成时要执行的延续。这意味着在
async
方法中,当到达第一个
wait
时,控件实际上返回给调用者一个热任务。当一个
wait
到达该延续中时,它会再次注册一个延续,以此类推

因此,在您的情况下,执行顺序应为:

  • 第一个循环的同步部分
  • 第二个循环的同步部分
  • 第一个循环的延续
  • 第二个循环的延续
  • 调用方在第一个循环后的继续
  • 调用方在第二个循环后的继续

中间的连续性可以根据异步操作实际占用的时间而不同。


你可以想象这里有3种不同的流量。第一个调用执行两个
循环
调用的同步部分,启动两个
异步
操作和延续的并发流,然后向第一个调用注册一个延续,将向第二个调用注册一个延续。

yes
wait
yield
有一些相似之处。您拥有的是两个彼此异步执行的循环,因为在启动第二个循环之前,您没有等待第一个循环。每个循环中的每个迭代都按顺序执行(即与同一循环中的其他迭代同步)。出于这样的原因,我不建议使用
await
来实现并发。(也就是说,如果你要等待某件事,请在任务开始时执行。