当前位置: 首页 > news >正文

02020204 .NET Core重难点知识04-async和await原理揭秘、async背后的线程切换

02020204 .NET Core重难点知识04-async和await原理揭秘、async背后的线程切换

1. async、await原理揭秘(视频Part2-6)

1.1 源代码
using System;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;namespace Demo02
{class Program{static async Task Main(string[] args){using (HttpClient httpClient = new HttpClient()){string html = await httpClient.GetStringAsync("https://www.baidu.com");Console.WriteLine(html);}string destFilePath = "d:/1.txt";string content01 = "hello async and await";await File.WriteAllTextAsync(destFilePath, content01);string content02 = await File.ReadAllTextAsync(destFilePath);Console.WriteLine("文件内容:" + content02);}}
}
1.2 对上述代码进行反编译
图片链接丢失
  • 使用反编译器,选择C#版本为C# 4.0/VS 2010,可以发现微软将上述代码反编译为了一个类
    d__0。
    • 编译器将static async Task Main(string[] args) {...}这个方法反编译为了如下两个Main方法。
    • 编译器生成的类名都比较怪,避免和我们自己写的类重复。
// Main方法1:<Main>(string[]): void → 无返回值的Main方法,反编译的代码段:
using System.Diagnostics;[DebuggerStepThrough]
private static void <Main>(string[] args)
{Main(args).GetAwaiter().GetResult(); // 调用了返回值为Task的Main方法
}
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// Main方法2:Main(string[]): Task → 返回值为void的异步方法,反编译的代码段:
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;[AsyncStateMachine(typeof(<Main>d__0))]
[DebuggerStepThrough]
private static Task Main(string[] args)
{<Main>d__0 stateMachine = new <Main>d__0(); // 创建了一个<Main>d__0类对象stateMachine.<>t__builder = AsyncTaskMethodBuilder.Create();stateMachine.args = args;stateMachine.<>1__state = -1;stateMachine.<>t__builder.Start(ref stateMachine);return stateMachine.<>t__builder.Task;
}
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
综上:
1. 我们编写代码时声明的static async Task Main(string[] args) {...}这个Main方法,已经不是传统的Main方法了。
2. 真正的Main方法是<Main>(string[]): void。
3. 而Main(string[]): Task是编译器自动生成的
  • 查看反编译的
    d__0类。
using System;
...
using System.Runtime.CompilerServices;[CompilerGenerated]
private sealed class <Main>d__0 : IAsyncStateMachine
{public int <>1__state;public AsyncTaskMethodBuilder <>t__builder;public string[] args;private string <destFilePath>5__1; // 将方法中的局部变量反编译为了成员变量private string <content01>5__2;...private void MoveNext() // 将static async Task Main(string[] args) {...}这个Main方法切割成了若干块{int num = <>1__state;try{...Console.WriteLine("文件内容" + <content02>5__3);}catch (Exception exception){...}}...
}说明:
1. 关键词:状态机,课后查一下。
2. MoneNext()方法会被调用多次,每一次根据条件的不同,它执行不同的case。
1.3 结论
  • 用ILSyp反编译dll(.ext只是Windows下的启动器)成C# 4.0版本,就能看到底层的IL代码。
  • await,async是“语法糖”,最终编译成状态机调用。
  • async的方法会被C#编译器编译成一个类,会主要根据await调用进行切分为多个状态。
    • 对async方法的调用会被拆分为MoveNext的调用。
  • 用await看似是等待,经过编译后,其实没有wait。
    • 用await看似是等待,其实反编译之后并没有等待。

2. async背后的线程切换(视频Part2-7)

  • 抛出两个问题:
    • 为何C#编译器要把一个async方法拆分为多个状态然后分为多次调用?
    • 异步的可以避免线程等待耗时操作,但是await还是等待?
  • 解答:await调用的等待期间,.NET会把当前的线程返回给线程池。当等待的异步方法调用执行完毕之后,框架会从线程池再取出一个线程执行后续的代码。
  • Thread.CurrentThread.ManagedThreadId获取当前线程Id,用于验证“在耗时异步(写入大量字符串)操作前后分别打印线程Id“。
using System;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;namespace Demo02
{class Program{static async Task Main(string[] args){Console.WriteLine(Thread.CurrentThread.ManagedThreadId); // 获取写入前线程IdStringBuilder sb = new StringBuilder();for (int i = 0; i < 10000; i++){sb.Append("Qinway");}await File.WriteAllTextAsync(@"..\01.txt", sb.ToString());Console.WriteLine(Thread.CurrentThread.ManagedThreadId); // 获取写入后线程IdConsole.ReadLine();}}
}控制台输出:
1
4说明:
1. 大概率每次运行后线程Id都不一样,如果写入内容少,会发现线程Id不变。
理解 → 点餐时,A服务员引导你做到餐桌上。点餐事件如果比较长,等待期间,A服务员可能去服务其它客人了。当你点餐完成下单时,可能是B服务员来服务你下单。
2. CLR未来的的优化方向:到要等待的时候,如果发现已经执行结束了,那就没有必要再切换线程,剩下的代码就继续在之前的线程上继续执行。
2.1 线程切换并不好,计算机底层在做线程切换的时候,会导致很多资源的切换,性能比较低。
2.2 如果写async和await程序的时候,在不影响系统并发情况下,尽量避免线程切换对系统的并发性能也是有很大帮助的。
2.3 理解这些对后续编写异步代码时很有帮助。

结尾

书籍:ASP.NET Core技术内幕与项目实战

视频:https://www.bilibili.com/video/BV1pK41137He

著:杨中科

ISBN:978-7-115-58657-5

版次:第1版

发行:人民邮电出版社

※敬请购买正版书籍,侵删请联系85863947@qq.com※

※本文章为看书或查阅资料而总结的笔记,仅供参考,如有错误请留言指正,谢谢!※

http://www.sczhlp.com/news/34885/

相关文章:

  • 测试实践
  • 集合--介绍、框架体系、单列集合(Collection、List接口介绍,常用方法,遍历方式)
  • 广州网站开发水平广州亦客网络专业做app软件开发公司
  • 织梦素材网站模板免费制作链接
  • 南京建设教育网站河南纯手工seo
  • 最专业的佛山网站建设价格百度推广费用怎么算
  • 关于并查集 - Ghost
  • 变量作用域详细解释
  • 网站维护的主要内容包括2022年app拉新推广项目
  • 做网站推广常识题库及答案青岛百度网站排名优化
  • wordpress绕绕国外seo比较好的博客网站
  • wordpress 显示缩略图优化培训内容
  • wangz网站建设宁波seo优化项目
  • 网站开发要学什么河南新闻头条最新消息
  • 太原网站开发工程师seo快速排名利器
  • AT_abc277_c [ABC277C] Ladder Takahashi 题解
  • wordpress悬浮菜单厦门网站优化
  • 怎么才能搜索到自己做的网站seo推广外包报价表
  • 个人可以做商城网站吗青岛关键词网站排名
  • 男女做暖暖其他网站百度广告一天多少钱
  • 珠海网站建设网络公司怎么样交友网站有哪些
  • 做推广自己找网站百度权重怎么看
  • 温州专业微网站制作多少钱大地seo视频
  • 娱乐类网站怎么建设seo 的作用和意义
  • 定制网站开发seo怎么快速提高排名
  • 营销网站建设的原则百度竞价培训
  • 网站内容优化方法有哪些内容免费推广网站平台
  • wordpress xiu 5.5信阳搜索引擎优化
  • 注册企业查询汨罗网站seo
  • 正定县建设局 网站西安疫情最新情况