C#多线程(5)——异步方法async与await

在上一章节中,为大家介绍了C#多线程(4)——任务并行库TPL,TPL是从.NetFramwork4.0后引入的基于异步操作的一组API,核心关注于任务【 T a s k 和 T a s k < T > \textcolor{red}{Task 和 Task<T>} TaskTask<T>】。简化了我们异步编程的步骤,但在C#5.0时,引入了新的语言特性—— 异步方法 \textcolor{red}{异步方法} 异步方法,是一种语法糖,是TPL之上的更高级别的抽象,它遵循了基于任务的异步模式,仅仅只使用了async与await关键字,更加简化了异步编程,可以避免性能瓶颈并增强应用程序的总体响应能力。

1 异步方法

  • 异步方法是用 a s y n c \textcolor{blue}{async} async关键字修饰的方法,通常方法的名称会以Async关键字结尾。官方提供了大量的异步方法。
  • 方法的返回值有两种 【 T a s k ,方法体中无 r e t u r n 语句和 T a s k < T > 方法体中 r e t u r n T \textcolor{red}{Task ,方法体中无return语句 和 Task<T> 方法体中return T } Task,方法体中无return语句和Task<T>方法体中returnT】,这个与TPL模型的任务模型是一致的,都是对异步逻辑的封装
  • 异步方法通常包含至少一个 await 表达式,该表达式标记一个点,在该点上,直到等待的异步操作完成方法才能继续。
  • .NET Framework 4.5 或更高版本以及 .NET Core 包含许多异步方法。 例如,System.IO.Stream 类包含 CopyToAsync、ReadAsync 和 WriteAsync 等方法,以及同步方法 CopyTo、Read 和 Write。
 public static async Task<int> GetUrlContentLengthAsync(){HttpClient client = new HttpClient();Task<string> getStringTask = client.GetStringAsync("https://learn.microsoft.com/dotnet");Console.WriteLine("GetUrlContentLengthAsync 方法中的的Independent work"); //执行不依赖于 GetStringAsync 得出的最终结果的其他工作string contents = await getStringTask;return contents.Length; //返回值被包装为Task<string>类型
}

2 async、await原理

使用ILSpy对.dll文件进行进行反编译知,async await是语法糖,底层是 状态机 \textcolor{red} {状态机} 状态机的调用。async标注的方法会被反编译成一个类,会根据await的调用被切分为多个状态,
对async方法的调用会被拆分成MoveNext的调用(根据状态多次进入switch判断体)

在这里插入图片描述

3 异步方法与多线程的关系

异步方法旨在成为非阻止操作,即不阻塞异步方法调用方的线程。 \textcolor{red}{异步方法旨在成为非阻止操作,即不阻塞异步方法调用方的线程。} 异步方法旨在成为非阻止操作,即不阻塞异步方法调用方的线程。

await调用的等待期间,.Net会把当前的线程返回给线程池,等异步方法调用执行完成后,框架会从线程池中再取一个线程执行后续的代码(可能与前一个线程相同,也有可能是一个新的线程,这取决于CPU对线程池中线程的调度。await关键字前后可能是不一样的线程)。
线程的切换,主要取决于异步方法中的任务类型及实际CLR对线程的调度:
- I O 密集型 \textcolor{blue}{IO密集型} IO密集型:大部分时间都是cpu在等IO的读写操作。如网络请求数据、访问数据库或读取和写入到文件系统
- C P U 密集型 \textcolor{blue}{CPU密集型} CPU密集型:例如执行成本高昂【耗时长,占用大量内存空间】的计算,

测试 I O 密集型任务, M a i n 方法中关键代码块如下。 \textcolor{red}{测试IO密集型任务, Main方法中关键代码块如下。} 测试IO密集型任务,Main方法中关键代码块如下。

Console.OutputEncoding = Encoding.UTF8;string des = "E:\\logs\\2.txt";//定义一个异步方法,从指定的url下载html内容后再写入到本地文件夹中。async Task DownloadFromUrlAsycn(string filename){using (HttpClient client = new HttpClient()){Console.WriteLine("下载前 ,ThreadId is {0},是否为线程池线程{1}", Thread.CurrentThread.ManagedThreadId,Thread.CurrentThread.IsThreadPoolThread);//获得url的页面资源 (网络传输,属于IO密集型的任务,此时CPU空闲,为了充分的利用CPU,可能会出现CPU上下文的切换,await前后发现线程的切换)string s = await client.GetStringAsync("https://learn.microsoft.com/dotnet");Console.WriteLine("下载后 ,ThreadId is {0},是否为线程池线程{1}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);Console.WriteLine("写入文件前 ,ThreadId is {0},是否为线程池线程{1}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);//写入执行资源文件await File.WriteAllTextAsync(filename, s);Console.WriteLine("写入文件后 ,ThreadId is {0},是否为线程池线程{1}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);}}Console.WriteLine("方法前,ThreadId is {0},是否为线程池线程{1} ", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);await DownloadFromUrlAsycn(des);Console.WriteLine("方法后,ThreadId is {0},是否为线程池线程{1} ", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);Console.ReadKey();

运行Main方法后,得到下图结果

在这里插入图片描述

可以发现,切换线程主要是发生在网络传输和文件写入的前后【IO读写动作】,IO的读写是不需要使用CPU的,只需要发一个命令给硬盘即可,硬盘处理完后会再通知cpu继续处理。为了充分利用CPU在IO读写的阶段,通常会将线程返回到线程池中。该线程可以用于其他的CPU操作。

测试 C P U 密集型任务, M a i n 方法中关键代码块如下。 \textcolor{red}{测试CPU密集型任务, Main方法中关键代码块如下。} 测试CPU密集型任务,Main方法中关键代码块如下。

     Console.OutputEncoding = Encoding.UTF8;Console.WriteLine("方法前线程id为{0}", Thread.CurrentThread.ManagedThreadId);async Task GetStringAsync() {Console.WriteLine("方法中线程id为{0}",Thread.CurrentThread.ManagedThreadId);for (int i = 0; i < 5; i++) {Thread.Sleep(TimeSpan.FromSeconds(1)); //模拟CPU计算需要耗时};};await GetStringAsync();Console.WriteLine("方法后线程id为{0}", Thread.CurrentThread.ManagedThreadId);Console.WriteLine("");Task t=  Task.Run(()=>GetStringAsync()) ;t.Wait();Console.WriteLine(" Task.Run方法后线程id为{0}",    Thread.CurrentThread.ManagedThreadId); //对于CPU密集型的异步方法时,通常会等待一个使用 Task.Run 方法在后台线程启动的操作。

在这里插入图片描述

(1)当是一个CPU密集型的异步方法时,线程的切换涉及到很多资源的消耗,在这种情况下,使用新的线程去执行异步方法的逻辑并不会优于同步执行的逻辑。所以await GetStringAsync()的前后都是使用同一个线程。
(2)综上所述,根据代码的验证我们可以知道异步方法并不能等价于多线程,调用异步方法时,并不是都会通过新的线程去执行异步逻辑,在没有线程切换的状态下【通常是CPU密集型的任务】,与同步方法是一致的。为了达到异步的效果,我们可以使用Task.Run()的方法,在后台线程中执行异步操作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/741297.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

轴向磁通电机(轴向电机)属于高效节能型电机 本土企业已具备高性能产品生产实力

轴向磁通电机&#xff08;轴向电机&#xff09;属于高效节能型电机 本土企业已具备高性能产品生产实力 按照磁通路径方向不同&#xff0c;电机可分为径向磁通电机以及轴向磁通电机两种类型。轴向磁通电机又称轴向电机&#xff0c;指电机旋转轴与磁通方向平行的磁通电机。与径向…

Ai-M61-32SU+字库+LCD

Ai-M61-32SU 有4M flash&#xff0c;可以下载一个200多K的GB2312_80字库 一、将gb2312_80.bin(字库文件)烧录到Ai-M61-32SU中 1、将gb2312_80.bin放到工程的根目录 2、修改flash_prog_cfg.ini文件&#xff0c;增加了partition和media部分 [cfg] # 0: no erase, 1:programmed …

js视频上传的方法

一、视频上传于图片上传类似他们的上传方法一样。路径不同标签不同&#xff1b; 二、直接上效果 三、直接上代码 // // 上传图片 let urls "https://wwz.jingyi.icu/"; let a $("form img") // console.log(a);function fl() {let read document.getE…

探索制氮机在农产品保鲜中的应用方式

在现代生活中&#xff0c;农产品保鲜成为老生常谈的话题&#xff0c;水果数次厂商总是在为如何使水果蔬菜能够保存时间长一点而发愁&#xff0c;而制氮机的出现则解决了这一难题&#xff0c;为农产品保鲜技术带来了革命性的变革。本期恒业通小编和您一起了解制氮机在水果,蔬菜保…

Pytorch基础(21)-- torch.repeat_interleave()方法

分享一下自己目前在维护的Github项目&#xff0c;由于本人博士阶段接触了一个全新的研究方向-----使用机器学习、强化学习、深度学习等方法解决组合优化问题&#xff0c;维护这个项目的目的&#xff1a; &#xff08;1&#xff09;记录自己阅读过的paper&#xff0c;同时分享一…

【数学建模】熵权法 Python代码

熵权法是一种客观的赋权方法&#xff0c;它可以靠数据本身得出权重。 依据的原理&#xff1a;指标的变异程度越小&#xff0c;所反映的信息量也越少&#xff0c;其对应的权值也应该越低。 import numpy as np#自定义对数函数mylog&#xff0c;用于处理输入数组中的0元素 def m…

ROS机器人操作系统底层原理及代码剖析

本文介绍ROS机器人操作系统&#xff08;Robot Operating System&#xff09;的实现原理&#xff0c;从最底层分析ROS代码是如何实现的。 1、序列化 把通信的内容&#xff08;也就是消息message&#xff09;序列化是通信的基础&#xff0c;所以我们先研究序列化。 尽管笔者从事…

jenkins部署go应用 基于docker

丢弃旧的的构建 github 拉取代码 拉取代码排除指定配置文件 报错 环境变量失效 服务器版本为1.21.6 但是一直没有生效

字符串|替换数字

卡码网题目链接 #include<iostream> using namespace std; int main() {string s;while (cin >> s) {int count 0; // 统计数字的个数int sOldSize s.size();for (int i 0; i < s.size(); i) {if (s[i] > 0 && s[i] < 9) {count;}}// 扩充字符…

6.同步异步、正则表达式

JS执行机制 js的特点&#xff1a;单线程&#xff0c;同一时间只能做一件事 可以通过多核CPU解决这个问题&#xff0c;允许js脚本创建多个线程&#xff0c;于是js出现了同步和异步 同步 程序执行的时候按照顺序依次执行 异步 程序执行的时候&#xff0c;会跳过某个步骤继续…

基于Springboot的驾校预约学习系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的驾校预约学习系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构…

fate隐私求交案例

intersect组件是解决纵向联邦学习中的隐私求交问题 fate隐私求交的方式有三种&#xff1a;raw,rsa,dh。raw方式不安全&#xff0c;rsa和dh方式是安全的&#xff0c;dh是基于对称加密的安全交集 rsa是基于RSA(非对称加密)的安全交集&#xff0c;&#xff0c;dh方法也用于安全的…

供应链金融新篇章:2001-2022年上市公司金融水平测算概览

数据说明&#xff1a;参考周兰和吴慧君&#xff08;2022&#xff09;的方法测算出2001-2022年上市公司供应链金融水平&#xff0c;供大家研究使用。数据来源&#xff1a;企业年报等。时间跨度&#xff1a;2001-2022年 数据范围&#xff1a;A股上市公司 数据指标&#xff1a;…

实现swiper 3d 轮播效果

先上个效果图&#xff0c;代码可以直接拿~ 安装swiper和vue-awesome-swiper 因为项目用的是nuxt2&#xff0c;所以考虑到swiper的兼容问题&#xff0c;选择的是"swiper": “^5.2.0” 首先是安装swiper和vue-awesome-swiper&#xff0c;并指定版本 npm install s…

基于Unity3D的AVG卡牌游戏设计与实现

目 录 摘 要 I Abstract II 引 言 1 1 相关技术 3 1.1 C# 3 1.2 Unity3D 3 1.3 UGUI 3 1.4 XML 4 1.5 原型设计模式 4 1.6 本章小结 4 2 系统分析 5 2.1 用户需求 5 2.2 功能需求 5 2.3 非功能需求 6 2.4 本章小结 6 3 系统设计 7 3.1 系统该要设计 7 3.2 系统详细设计 7 3.2.…

数组和指针笔试题目解析---掌握他们拿下指针魔鬼

目录 一、前言二、一维数组2.1代码2.2分析2.3验证运行结果 三、字符数组3.1代码13.1.1分析3.1.2验证运行结果 3.2代码23.2.1分析3.2.2验证运行结果 3.3代码33.3.1分析3.3.2验证运行结果 3.4代码43.4.1分析3.4.2验证运行结果 3.5代码53.5.1分析3.5.2验证运行结果 3.6代码63.6.1分…

基于SpringBoot和VUE技术的智慧生活商城系统设计与实现

** &#x1f345;点赞收藏关注 → 私信领取本源代码、数据库&#x1f345; 本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目&#xff0c;希望你能有所收获&#xff0c;少走一些弯路。&#x1f345;关注我不迷路&#x1f345;** 一、研究背景…

Net Core 使用Mongodb操作文件(上传,下载)

Net Core 使用Mongodb操作文件&#xff08;上传&#xff0c;下载&#xff09; 1.Mongodb GridFS 文件操作帮助类。 GridFS 介绍 https://baike.baidu.com/item/GridFS/6342715?fraladdin DLL源码&#xff1a;https://gitee.com/chenjianhua1985/mongodb-client-encapsulati…

STM32点亮LED灯与蜂鸣器发声

STM32之GPIO GPIO在输出模式时可以控制端口输出高低电平&#xff0c;用以驱动Led蜂鸣器等外设&#xff0c;以及模拟通信协议输出时序等。 输入模式时可以读取端口的高低电平或电压&#xff0c;用于读取按键输入&#xff0c;外接模块电平信号输入&#xff0c;ADC电压采集灯 GP…

论坛管理系统|基于Spring Boot+ Mysql+Java+B/S架构的论坛管理系统设计与实现(可运行源码+数据库+设计文档+部署说明+视频演示)

推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 目录 目录 前台功能效果图 管理员功能登录前台功能效果图 用户功能模块 系统功能设计 数据库E-R图设计 l…