当前位置: 首页 > 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根本不是真的“等待”,而是靠状态机和等待器来实现的异步协作。
    • 强调一下异步编程的好处,比如响应快、省资源、能扛更多活儿,还有啥场景适合用它。

相关文章:

  • YOLOv2 性能评估与对比分析详解
  • 操作系统内核调度:抢占式与非抢占式及RTOS中的应用
  • 目标检测与分割:深度学习在视觉中的应用
  • 代码随想录算法训练营Day30
  • NO.93十六届蓝桥杯备战|图论基础-拓扑排序|有向无环图|AOV网|摄像头|最大食物链计数|杂物(C++)
  • linux ceres库编译注意事项及测试demo
  • Java学习手册:Java线程安全与同步机制
  • V型调节阀:专为解决锂电池行业碳酸锂结晶介质的革命性方案-耀圣
  • 《Training Language Models to Self-Correct via Reinforcement Learning》全文翻译
  • go入门记录
  • 金能电力领跑京东工业安全工器具赛道 2025年首季度数据诠释“头部效应”
  • 基于工业操作系统构建企业数字化生态的实践指南
  • 编码风格(二)——使用具有风格的语言特性、格式和风格的挑战
  • leetcode0547. 省份数量-medium
  • 报告分享 | 模型上下文协议(MCP):实现大模型与外部工具的标准化交互
  • L1-6 大勾股定理(PTA)
  • Web三漏洞学习(其二:sql注入)
  • Chat2DB 数据库客户端邀请码
  • 智能外呼系统:企业数字营销的AI新引擎
  • 【网络篇】UDP协议的封装分用全过程
  • AI换脸侵权案入选最高法典型案例:明晰人工智能使用边界
  • 年近九旬的迪图瓦,指挥能量比盛年更为强劲
  • 我国与沙特签署《核能发展安全与安保合作谅解备忘录》
  • 首届中国—海湾阿拉伯国家合作委员会和平利用核技术论坛在成都召开
  • 揭晓!人形机器人半马完赛奖+专项奖发布
  • 对话地铁读书人|来自大学教授的科普:读书日也是版权日