什么时候“等待"立即离开方法,什么时候不离开? [英] When does 'await' immediately leave a method and when does it not?

查看:61
本文介绍了什么时候“等待"立即离开方法,什么时候不离开?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在使用async-await的程序中,我的理解是这样的:

In programs utilizing async-await, my understanding is like this:

  • 未等待的异步方法将在后台(?)运行,其余代码将在该未等待的方法完成之前继续执行
  • 已等待IS的异步方法将等待该方法完成,然后再继续进行下一行代码

下面的应用程序是我写的,用于检查以上陈述是否正确.

The application below was written by me to check if the above statements are correct.

using System;
using System.Threading.Tasks;

namespace ConsoleApp3
{
    class Program
    {
        static async Task Main(string[] args)
        {
            Console.WriteLine("Hello World!");

            DoJob();

            var z = 3;

            Console.ReadLine();
        }

        static async Task DoJob()
        {
            var work1 = new WorkClass();
            var work2 = new WorkClass();

            while (true)
            {
                await work1.DoWork(500);
                await work2.DoWork(1500);
            }
        }
    }

    public class WorkClass
    {
        public async Task DoWork(int delayMs)
        {
            var x = 1;

            await Task.Delay(delayMs);

            var y = 2;
        }
    }
}

以下是我的一些观察结果:

Here are some of my observations:

  • 不等待 DoJob(); 调用.但是,调试器向我展示了DoJob内部的代码正在执行,就像它是普通的非异步方法一样.
  • 当代码执行到 await work1.DoWork(500); 时,我认为好吧,所以也许现在将保留 DoJob 方法,然后var z = 3; 会被执行吗?毕竟,"await"应该离开该方法."实际上,它只是进入 DoWork ,而没有离开 DoJob - var z = 3; 仍未执行.
  • 最后,当执行到达 await Task.Delay(delayMs); 时,剩下 DoJob ,而 var z = 3; 是到达.之后,执行 Delay 之后的代码.
  • The DoJob(); call is not awaited. However, the debugger shows me that the code inside of DoJob is being executed, just as if it was a normal non-async method.
  • When code execution gets to await work1.DoWork(500);, I would think "OK, so maybe now the DoJob method will be left and var z = 3; will be executed? After all, 'await' should leave the method." In reality, it just goes into DoWork and doesn't leave DoJob - var z = 3; is still not executed.
  • Finally, when execution reaches await Task.Delay(delayMs);, DoJob is left, and the var z = 3; is reached. After that, code after the Delay is executed.

我不明白的事情:

  • 为什么等待Task.Delay(delayMs); 离开 DoJob 方法,但是 await work1.DoWork(500); 却没有?
  • 我看到 DoJob 正常执行.我以为会在后台完成(也许是通过线程池线程之一?).如果这是一个长时间运行的方法,它看起来可能会阻塞线程,对吗?
  • Why does await Task.Delay(delayMs); leave the DoJob method, but await work1.DoWork(500); does not?
  • I see that DoJob is executing normally. I thought it would be done in the background (maybe by one of the thread pool threads?). Looks like it could block the thread if it was some long-running method, am I right?

推荐答案

编译器将 async 方法中的代码拆分为多个块.在第一个 await 之前1个,在每个 await 之间的1个,以及在最后一个 await 之后的1个.

The compiler splits the code in an async method in chunks. 1 before the first await and 1 between each await and 1 after the last await.

执行将在第一个未完成的等待者或方法结束时返回给调用者.

The execution will return to the caller at the first non completed awaiter or the end of the method.

此方法将在完全执行后仅返回完成的 Task :

This method will only return a completed Task after fully executed:

async Task M1() => await Task.CompletedTask;

此方法将仅返回不完整的 Task ,该任务将在 Task.Dealy(1000)返回的 Task 完成时完成:

This method will only return an incomplete Task that will complete when the Task returned by Task.Dealy(1000) is completed:

async Task M2() => await Task.Delay(1000);

这是一个小例子:

static async Task Main(string[] args)
{
    var t = TwoAwaits();
    Console.WriteLine("Execution returned to main");
    await t;
}
private static async Task TwoAwaits()
{
    Console.WriteLine("Before awaits");
    await Task.CompletedTask;
    Console.WriteLine("Between awaits #1");
    await Task.Delay(1000);
    Console.WriteLine("Between awaits #2");
    await Task.Delay(1000);
    Console.WriteLine("After awaits");
}
/*
Before awaits
Between awaits #1
Execution returned to main
Between awaits #2
After awaits
*/

这篇关于什么时候“等待"立即离开方法,什么时候不离开?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆