C# 细说async/await的用法

目录

一,引言

二,实例演示

2.1 多线程同步执行下载任务,任务完成后通知

2.2 异步执行下载任务,任务完成后通知

三,async/await的用法

3.1 跨线程修改UI控件

3.2 异步获取数据


一,引言

首先先来区分一下,同步方法,异步方法和多线程:

  • 同步方法:调用时需要等待返回结果(相当于阻塞了该线程),才可以继续往下执行业务
  • 异步方法:调用时无须等待返回结果(等待时释放线程),可以继续往下执行业务
  • 多线程:在主线程之外开启一个新的线程去(增加线程,同步执行)执行业务

 关于async/await:

  1.  async和await关键字是C# 5.0时代引入的,它是一种异步编程模型
  2. 它们本身并不创建新线程,但可以在自行封装的async中利用Task.Run开启新线程
  3. 方法体中使用await,方法也必须声明为async(成对出现),如果没有await,async关键字也没有意义。

async/await的理解:

个人理解:await可以看着是代码执行的分裂点,当程序执行到await后面的语句时,首先系统会将当前的线程释放(回归线程池,其他程序可调用),并捕获当前上下文(打上标记),进入等待(注意:期间没有线程阻塞)。当await后语句执行完毕,根据标记点调用线程(从线程池随机捕获线程,有概率是原来的线程)执行下面的语句。

二,实例演示

2.1 多线程同步执行下载任务,任务完成后通知

static void Main(string[] args){DownloadHandle();Console.ReadLine();}public static  void DownloadHandle(){Console.WriteLine("下载开始!->主线程ID:" + Thread.CurrentThread.ManagedThreadId);var t= Download();Task.WaitAll(t);Console.WriteLine("下载完成!->主线程ID:" + Thread.CurrentThread.ManagedThreadId);}public static Task Download(){return Task.Run(() =>{Console.WriteLine("下载线程ID:->" + Thread.CurrentThread.ManagedThreadId);Console.WriteLine("10%");Console.WriteLine("30%");Console.WriteLine("50%");Console.WriteLine("60%");Console.WriteLine("80%");Console.WriteLine("99%");Console.WriteLine("100%");});}

结果输出:

可以看的,在多线程下载任务时,通过Task.WaitAll(t) 等待线程执行完毕后,主线程一直处于阻塞状态。

2.2 异步执行下载任务,任务完成后通知

        static void Main(string[] args){DownloadHandle();Console.ReadLine();}public static async void DownloadHandle(){Console.WriteLine("下载开始!->主线程ID:" + Thread.CurrentThread.ManagedThreadId);await Download();Console.WriteLine("下载完成!->主线程ID:" + Thread.CurrentThread.ManagedThreadId);}public static Task Download(){return Task.Run(() =>{Console.WriteLine("下载线程ID:->" + Thread.CurrentThread.ManagedThreadId);Console.WriteLine("10%");Console.WriteLine("30%");Console.WriteLine("50%");Console.WriteLine("60%");Console.WriteLine("80%");Console.WriteLine("99%");Console.WriteLine("100%");});}

可以看的,在异步下载任务时,主线程未被阻塞。

异步方法async/await的返回值类型一般都是Task或者Task<T>类型的,当返回值为Task时(即方法的返回值类型为void),我们可以直接return Task.Run(()=>{}),而不必await Task.Run(()=>{}),这样也可从一定程度上提高代码执行效率。另外,不推荐使用async 修饰void返回值,会有异常处理方面的问题。

三,async/await的用法

async/await并不能提升代码的执行速度,但可以提高响应能力(吞吐量),即使用异步方式在同一时间可以处理更多的请求。

  • 使用同步方式,线程会被耗时操作一直占用,直到耗时操作结束;
  • 使用异步方式,程序走到await关键字会立即return,释放线程,剩下的代码将放到一个回调,耗时操作完成时才会回调执行。

因此:

  • 对于计算密集型工作,使用多线程
  • 对于IO密集型工作,采用异步机制

从代码整体的架构设计来说,由于async/await语法容易使得程序被await传染,因此不要从最里面的方法启动线程,而是把启动线程的代码放到最外面,这样一来绝大部分方法就都不再需要用async修饰了,方法就都可以用正常的方式开发了。

3.1 跨线程修改UI控件

通过async/await的机制,可以非常简洁轻松的实现跨线程修改UI控件的问题,也不用使用Invoke。(因为本质上还是在原来的线程上修改的,还没有阻塞UI界面)

private async void button1_Click(object sender, EventArgs e){var t = Task.Run(() => {Thread.Sleep(5000);return "Hello I am TimeConsumingMethod";});textBox1.Text = await t;}

3.2 异步获取数据

在写后端的数据异步处理时,通过async/await语法也可轻易实现,为了防止async/await语法传染,将启动线程的代码放在了最外层,这样在Click事件中就可以正常调用了,不用在增加async关键字了。

 private void button2_Click(object sender, EventArgs e){AsyncFunc();}private async Task AsyncFunc(){DataTable dt = await FecthData();this.dataGridView1.DataSource = dt;}private async Task<DataTable> FecthData(){DataTable dt = null;await Task.Run(() =>{dt = new DataTable();dt.Columns.Add("id", typeof(int));dt.Columns.Add("name");for (int i = 0; i < 10000; i++){dt.Rows.Add(new object[] { i, "name" + i.ToString() });}Thread.Sleep(1000);});return dt;}

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

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

相关文章

基于html2canvas和jspdf将document DOM节点转换为图片生成PDF文件,并下载到本地

这里要用到html2canvas将document DOM节点转换为图片&#xff0c;并下载到本地_你挚爱的强哥的博客-CSDN博客前端用原生js编辑文件内容→创建生成文件(格式可以自定义)→下载文件_你挚爱的强哥的博客-CSDN博客。会自动创建一个html文件。https://blog.csdn.net/qq_37860634/art…

解决 Qt 下载安装太慢的办法

Qt 现在新的版本都是采用在线安装&#xff0c;那速度实在是.... 找了一些方法&#xff0c;原理就是用 Fiddler 来代理&#xff0c;然后替换掉 url 成清华的镜像地址&#xff0c;这样就相当于直接从清华安装了&#xff0c;嘎嘎快 打开 Fiddler, 打开 Qt 安装程序&#xff0c;在…

安达发|某大厂使用APS计划排程真实成功案例

在很多群里、朋友圈、公众号上可以看到&#xff0c;很多精益咨询老师认为&#xff0c;不仅ERP不啥用&#xff0c;APS更是无聊之举&#xff0c;而且肯定是用不好的。但&#xff0c;事实上可能还真不是这样的。 一个深圳的客户&#xff0c;用了APS以后&#xff0c;不仅装配的齐套…

图论 并查集 模拟 位运算—题841、127、684、685、657、31、463、1356 C++实现与有向图 无向图 并查集总结

文章目录 841.钥匙和房间DFSBFS 127. 单词接龙684.冗余连接685.冗余连接II657. 机器人能否返回原点31.下一个排列463. 岛屿的周长解法1解法2 1356. 根据数字二进制下 1 的数目排序解法1解法2 注意点 图论&#xff1a;题841、127 并查集&#xff1a;题684、685 模拟&#xff1a;…

一百三十、海豚调度器——用DolphinScheduler定时调度HiveSQL任务

一、目标 用海豚调度器对Hive数仓各层数据库的SQL任务进行定时调度。比如&#xff0c;DWD层脱敏清洗表的动态插入数据、DWS层指标表的动态插入数据 二、工具版本 1、海豚调度器&#xff1a;apache-dolphinscheduler-2.0.5-bin.tar.gz 2、Hive&#xff1a;apache-hive-3.1.2…

完整的电商平台后端API开发总结

对于开发一个Web项目来说&#xff0c;无论是电商还是其他品类的项目&#xff0c;注册与登录模块都是必不可少的&#xff1b;注册登录功能也是我们在日常生活中最长接触的&#xff0c;对于这个业务场景的需求与逻辑大概是没有什么需要详细介绍的&#xff0c;市面上常见的邮箱注册…

PyCharm 常用快捷键

目录 1、代码编辑快捷键 2、搜索/替换快捷键 3、代码运行快捷键 4、代码调试快捷键 5、应用搜索快捷键 6、代码重构快捷键 7、动态模块快捷键 8、导航快捷键 9、通用快捷键 1、代码编辑快捷键 序号快捷键作用1CTRLALTSPACE快速导入任意类2CTRLSHIFTENTER代码补全3SHI…

关于你欠缺的NoSQL中的redis和mongoDB

文章目录 前言一、在string list hash结构中&#xff0c;每个至少完成5个命令&#xff0c;包含插入 修改 删除 查询&#xff0c;list 和hash还需要增加遍历的操作命令1、STRING类型2、List类型数据的命令操作&#xff1a;3、举例说明list和hash的应用场景&#xff0c;每个至少一…

数组的递归筛选

数组递归筛选 根据一个值筛选出来通过 includes 递归 const options [{name: "ikun",options: [{name: "YAY11",},],},{name: "YAY",}, ];function findValue(orgOptions,val) {let newArr1 []orgOptions.forEach(item>{if(item.options…

网络爬虫-网易易盾滑块验证码

首先打开易盾官网&#xff0c;依次单击“在线体验”和“滑块拼图”选项&#xff0c;出现如下图所示的滑块验证码&#xff0c;滑动后发现Network面板成功抓包。 如图所示 其中主要的加密参数可以看出来就是acToken以及cb 我们接着下断点往下走 我通过上图可以看到 acToken&#…

实例018 类似windows xp的程序界面

实例说明 在Windows XP环境下打开控制面板&#xff0c;会发现左侧的导航界面很实用。双击展开按钮&#xff0c;导航栏功能显示出来&#xff0c;双击收缩按钮&#xff0c;导航按钮收缩。下面通过实例介绍此种主窗体的设计方法。运行本例&#xff0c;效果如图1.18所示。 ​编辑…

适合小公司的自动化部署脚本

背景&#xff08;偷懒&#xff09; 在小小的公司里面&#xff0c;挖呀挖呀挖。快挖不动了&#xff0c;一件事重复个5次&#xff0c;还在人肉手工&#xff0c;身体和心理就开始不舒服了&#xff0c;并且违背了个人的座右铭&#xff1a;“偷懒”是人类进步的第一推动力。 每次想…