Lor*_*eno 2 c# multithreading asynchronous task async-await
在使用 async-await 的程序中,我的理解是这样的:
下面的申请是我写的,以检查上述陈述是否正确。
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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
以下是我的一些观察:
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执行之后的代码。我不明白的事情:
await Task.Delay(delayMs);离开DoJob方法,但await work1.DoWork(500);没有?DoJob正在正常执行。我认为它会在后台完成(也许由线程池线程之一?)。如果它是一些长时间运行的方法,它看起来可能会阻塞线程,对吗?编译器将async方法中的代码分成块。1 之前的第一个await和 1 之间的每个await和 1 之后的最后一个await。
执行将在第一个未完成的等待者或方法结束时返回给调用者。
此方法仅Task在完全执行后才返回完成:
async Task M1() => await Task.CompletedTask;
Run Code Online (Sandbox Code Playgroud)
此方法将只返回一个不完整的Task,当Task返回的完成时将Task.Dealy(1000)完成:
async Task M2() => await Task.Delay(1000);
Run Code Online (Sandbox Code Playgroud)
这是一个小例子:
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
*/
Run Code Online (Sandbox Code Playgroud)
为什么等待 Task.Delay(delayMs); 离开 DoJob 方法,但等待 work1.DoWork(500); 才不是?
因为这段代码:
await work1.DoWork(500);
Run Code Online (Sandbox Code Playgroud)
与此代码相同:
var task = work1.DoWork(500);
await task;
Run Code Online (Sandbox Code Playgroud)
所以,你的代码在调用方法第一,然后等待返回的任务。通常await所说的“等待方法调用”,但这并不是实际发生的情况——从技术上讲,首先(同步)完成方法调用,然后等待返回的任务。
我看到 DoJob 正在正常执行。我认为它会在后台完成(也许由线程池线程之一?)。
不; 对于真正的异步操作,没有线程被该操作阻塞。
如果它是一些长时间运行的方法,它看起来可能会阻塞线程,对吗?
是的。
我的理解是这样的
我建议阅读我的异步介绍以获得更好的心理框架。总之:
async启用await关键字。它还生成一个状态机来处理创建Task返回值之类的事情。await对“可等待的”(通常是任务)进行操作。首先,它会检查它是否已经完成;如果是,该async方法将继续同步执行。await(默认情况下)捕获其上下文并安排该async方法的继续在等待完成时在该上下文上运行。