了解C#等待运算符

只是一个学习者

我只是对C#的异步编程有一些基本的了解。据我了解,这段代码

statement1;
await statement2();
statement3;
statement4;

在逻辑上应等效于

statement1;
var awaiter = statement2().GetAwaiter();
awaiter.OnCompletion(() => {
    awaiter.GetResult();
    statement3;
    statement4;
});

因此,如果await代码中有一条语句,则以下所有语句仅在等待的任务完成后才开始执行。这似乎就像同步代码。该文档指出,该await语句将导致执行返回给调用者,并在等待的任务完成后恢复执行。但是在下面的示例中,我无法完全理解它是如何工作的。

using System;
using System.Threading.Tasks;

namespace ThreadTesting
{
    class Program
    {
        public static async Task Main(string[] args)
        {
            await DoSomething2(); // <------- B
            Console.WriteLine("Test!"); // <------- C
            Console.ReadKey(); // <------- D
        }

        public static async Task DoSomething2()
        {
            Console.WriteLine("Start DoSomething2"); 
            var i = await DoSomething(); // <------ A
            Console.WriteLine("End DoSomething2");
        }

        public static async Task<int> DoSomething()
        {
            Console.WriteLine("Start DoSomething1");
            await Task.Delay(10000);
            Console.WriteLine("Before returning from DoSomething1");
            return 88;
        }
    }
}

输出是

Start DoSomething2
Start DoSomething1
Before returning from DoSomething1
End DoSomething2
Test!

让我们以语句A为例。在这里等待DoSomething()在等待时,执行逻辑从DoSomething2()B返回并返回到B。据我所知,执行应在等待时继续执行语句C和D DoSomething2()(语句B)。但是结果表明该字符串"Test!"仅在程序末尾打印。为什么会这样?我的理解正确吗?

德米特里·伊万诺夫(Dmitry Ivanov)

要注意的是您的Main回报Task,因此它也async将被完全“阻止”。您的执行顺序将如下所示:

  1. Main() 开始
  2. Main到达await运算符,并Task使用其余方法创建一个看起来好像Main()已经停止,正在等待await结果
  3. DoSomething2() 启动并写入控制台“ Start DoSomething2”
  4. 它到达下一个await运算符,并Task使用其余DoSomething()方法创建另一个运算符
  5. DoSomething() 开始
  6. 它将写入控制台“ Start DoSomething1”
  7. 获取awat操作员并Task使用其余DoSomething()方法创建一个,等待延迟。
  8. 完成此Task操作后(经过延迟),DoSomething()将“从DoSomething1返回之前”写入控制台并返回88。
  9. Task创建的,DoSomething2()完成了方法的其余部分(将88分配i给控制台并将“从DoSomething1返回之前”写入控制台
  10. Task,在创建Main()完成,写“测试!” 进行控制台。

因此,“测试!” 最后是因为你的Main()回报Task如果您想要该行为,则可以期望将其交换Taskvoid

public static async void Main(string[] args)
{
    ...
}

然后,当到达await操作员位置时,Main()不会等待Task()完成并继续执行。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章