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

C#中async await异步关键字用法和异步的底层原理

目录

  • C#异步编程
    • 一、异步编程基础
    • 二、异步方法的工作原理
    • 三、代码示例
    • 四、编译后的底层实现
    • 五、总结

C#异步编程

一、异步编程基础

  1. 异步编程是啥玩意儿
    • 就是让程序在干等着某些耗时操作(比如等网络响应、读写文件啥的)的时候,能把线程腾出来干别的活儿,这样程序就能更灵敏、更高效啦。
    • 跟同步编程不一样,同步编程就是老老实实等着操作完成才继续往下走,线程就一直被占着,多浪费啊。
  2. 异步编程的好处
    • 响应快:比如在做UI界面的时候,用了异步编程,界面就不会卡啦,用户体验贼棒。
    • 省资源:不用让线程一直干等着,资源利用率就上去了。
    • 能扛更多活儿:面对一大堆并发操作的时候,异步编程能轻松搞定,扩展性杠杠滴。

二、异步方法的工作原理

  1. 异步方法咋被编译的
    • 你写个async修饰的方法,编译器就把它变成一个状态机啦。
    • 状态机会根据await表达式把方法拆成好多个状态,就跟玩拼图一样。
  2. 状态机是咋干活的
    • 状态机就是编译器生成的一个类,它得记着异步方法执行到哪儿了。
    • 核心就是MoveNext方法,它就像导演一样,指挥着异步操作一步步往下走。
    • 每碰到一个await,就切换一下状态。
  3. await底层是咋实现的
    • await就整出个等待器(awaiter),专门等着异步操作完成。
    • 要是操作还没完,await就记下当前状态,等操作完了再继续往下走。

三、代码示例

  1. HttpClient干异步网络请求
    • 弄个HttpClient对象,用来发HTTP请求。
    • GetStringAsync方法,就能异步拿到指定URL的网页内容啦。
    • 把拿到的内容打印出来,瞧一瞧成果。
using System;
using System.Net.Http;
using System.Threading.Tasks;namespace asyncawait原理1
{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);}}}
}
  1. 异步读写文件
    • File.WriteAllTextAsync方法,能把文本异步写到指定路径的文件里。
    • File.ReadAllTextAsync方法,就能把文件内容异步读出来。
    • 把读到的内容打印出来,看看对不对。
using System;
using System.IO;
using System.Threading.Tasks;namespace asyncawait原理1
{class Program{static async Task Main(string[] args){string txt = "hello world";string filename = @"E:\temp\1.txt";await File.WriteAllTextAsync(filename, txt);Console.WriteLine("写入成功");string s = await File.ReadAllTextAsync(filename);Console.WriteLine("文件内容:" + s);}}
}

四、编译后的底层实现

  1. 用ILSpy反编译DLL文件
    • ILSpy就是个反编译工具,能把DLL文件变回C#代码,方便咱们研究。
    • 把DLL文件加载到ILSpy里,就能看到编译后的代码啦。
[CompilerGenerated]
private sealed class <>c__DisplayClass0_0 : IAsyncStateMachine
{public int <>1__state;public AsyncTaskMethodBuilder <>t__builder;public string[] args;private string <>s__1;private string <>s__3;private string <>s__6;private HttpClient <httpClient>__4;private string <html>__5;private string <txt>__2;private string <filename>__7;private void MoveNext(){int num = this.<>1__state;try{TaskAwaiter<string> awaiter;TaskAwaiter awaiter2;switch (num){default:this.<httpClient>__4 = new HttpClient();goto case 0;case 0:try{awaiter = this.<httpClient>__4.GetStringAsync("https://www.baidu.com").GetAwaiter();if (!awaiter.IsCompleted){num = this.<>1__state = 0;this.<>t__builder.AwaitUnsafeOnCompleted(ref awaiter, ref this);return;}}catch (Exception exception){this.<>1__state = -2;this.<>t__builder.SetException(exception);return;}this.<html>__5 = awaiter.GetResult();Console.WriteLine(this.<html>__5);this.<txt>__2 = "hello yz";this.<filename>__7 = @"E:\temp\1.txt";awaiter2 = File.WriteAllTextAsync(this.<filename>__7, this.<txt>__2).GetAwaiter();if (!awaiter2.IsCompleted){num = this.<>1__state = 1;this.<>t__builder.AwaitUnsafeOnCompleted(ref awaiter2, ref this);return;}break;case 1:awaiter2 = this.<>s__1;this.<>s__1 = null;num = this.<>1__state = -1;break;}awaiter2.GetResult();Console.WriteLine("写入成功");this.<>s__3 = null;awaiter = File.ReadAllTextAsync(this.<filename>__7).GetAwaiter();if (!awaiter.IsCompleted){num = this.<>1__state = 2;this.<>t__builder.AwaitUnsafeOnCompleted(ref awaiter, ref this);return;}this.<>s__6 = awaiter.GetResult();Console.WriteLine("文件内容:" + this.<>s__6);this.<>s__6 = null;this.<>t__builder.SetResult();}catch (Exception exception){this.<>1__state = -2;this.<>t__builder.SetException(exception);return;}this.<>1__state = -1;}void IAsyncStateMachine.MoveNext(){// This method is implemented by the compiler-generated code.}[DebuggerHidden]private void SetStateMachine(IAsyncStateMachine stateMachine){this.<>t__builder.SetStateMachine(stateMachine);}void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine){this.SetStateMachine(stateMachine);}
}
  1. 看看编译后的状态机代码
    • 分析状态机类的结构,看看都有啥变量、MoveNext方法长啥样。
    • 瞧瞧awaiter咋用的,状态咋切换的。
  2. 理解MoveNext方法是干啥的
    • MoveNext就是状态机的发动机,它决定了异步方法咋执行。
    • 在这个方法里,会根据当前状态执行对应的代码,碰到await就暂停,安排好后续咋继续。

五、总结

  1. 异步方法编译过程回顾
    • 再唠唠async方法咋被编译成状态机的,状态机又咋根据await拆分方法、驱动异步操作的。
  2. await到底在干啥
    • 说白了,await根本不是真的“等待”,而是靠状态机和等待器来实现的异步协作。
    • 强调一下异步编程的好处,比如响应快、省资源、能扛更多活儿,还有啥场景适合用它。

http://www.mrgr.cn/news/98514.html

相关文章:

  • 怎么看英文论文 pdf沉浸式翻译
  • (二)Graspnet在mujoco的仿真复现(操作记录)
  • linux多线(进)程编程——(7)消息队列
  • Leetcode 2814. 避免淹死并到达目的地的最短时间【Plus题】
  • 第IV部分有效应用程序的设计模式
  • STM32F103_HAL库+寄存器学习笔记15 - 梳理CAN发送失败时,涉及哪些寄存器
  • 实战指南:封装Whisper为FastAPI接口并实现高并发处理-附整合包
  • 欧拉服务器操作系统安装MySQL
  • 单片机 + 图像处理芯片 + TFT彩屏 触摸开关控件 v1.2
  • Transformer-PyTorch实战项目——文本分类
  • (劳特巴赫调试器学习笔记)四、Practice脚本.cmm文件编写
  • C++第三方库【JSON】nlohman/json
  • Cribl 数据脱敏 -02 (附 测试数据)
  • 如何评估cpu的理论FLOPS能力
  • Windows 下 MongoDB ZIP 版本安装指南
  • libaom 码率控制实验:从理论到实践的深度探索
  • ReportLab 导出 PDF(文档创建)
  • C++函数
  • 深入解析分类模型评估指标:ROC曲线、AUC值、F1分数与分类报告
  • VLLM V1 serve在线推理基本流程