了解C#等待运算符 - 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。据我所知,在等待DoSomething2()时,执行应该继续执行语句C和D(语句B)。但是结果表明,字符串"Test!"仅在程序末尾打印。为什么会这样?我的理解正确吗?

参考方案

问题在于您的Main返回Task,因此它也完全是async,将被“停止”。您的执行顺序将如下所示:

Main()开始
Main进入await运算符,并使用其余方法创建Task。看来Main()已停止,正在等待await结果
DoSomething2()启动并写入控制台“ Start DoSomething2”
它到达下一个await运算符,并使用其余的Task方法创建另一个DoSomething()
DoSomething()开始
它将写入控制台“ Start DoSomething1”
获取awat运算符,并使用Task方法的其余部分创建一个DoSomething(),等待延迟。
Task完成之后(经过延迟),DoSomething()向控制台写入“从DoSomething1返回之前”,并返回88。
Task中创建的DoSomething2()完成该方法的其余部分(将88分配给i并向控制台写入“从DoSomething1返回之前”)
Task中创建的Main()完成,写“ Test!”。进行控制台。

因此,“测试!”最终是因为您的Main()返回Task。如果您想要这种行为,则期望将Task交换为void

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

然后,当到达await运算符时,Main()不会等待Task()完成,并将继续执行。

当回复有时是一个对象有时是一个数组时,如何在使用改造时解析JSON回复? - java

我正在使用Retrofit来获取JSON答复。这是我实施的一部分-@GET("/api/report/list") Observable<Bills> listBill(@Query("employee_id") String employeeID); 而条例草案类是-public static class…

Mongo汇总 - javascript

我的收藏中有以下文件{ "_id": ObjectId("54490b8104f7142f22ecc97f"), "title": "Sample1", "slug": "samplenews", "cat": …

如何在Wiremock中为JUNIT匹配精确的json - java

我正在使用Wiremock在Spring启动应用程序中模拟Junit的REST服务。我的问题是,我无法匹配多个匹配模式。 Junit.javaStringValuePattern pattern = WireMock.matching(".*"); givenThat(post(urlEqualTo("/softwares�…

多重处理:map与map_async - python

使用map和map_async有什么区别?将列表中的项目分配给4个进程后,它们是否运行相同的功能?因此,假设两者都在异步和并行运行是错误的吗?def f(x): return 2*x p=Pool(4) l=[1,2,3,4] out1=p.map(f,l) #vs out2=p.map_async(f,l) python大神给出的解决方案 将作业映射到流程…

jQuery DataTable TableTool在IE和Firefox中不起作用 - c#

我在MVC4 ASP.NET Web应用程序中使用Jquery DataTable TableTool。导出到Excel和PDF可以与Chrome完美配合。但是不能在IE和FireFox中使用。我的代码如下 dom: 'T<"clear">lfrtip', tableTools: { "sSwfP…