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.mzph.cn/news/1589.shtml

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

相关文章

网上书店管理系统

目录 一、系统需求分析 二、数据库概念结构设计 四、数据库物理实现 五、数据库功能调试 一、系统需求分析 需求概述 1.系统背景 当今互联网的迅速发展&#xff0c;使得人们获取信息变得极其便利。在从前&#xff0c;人们以线下书店购买书籍的方式获取知识&#xff0c;常常…

WEB:Confusion1

背景知识 SSTI漏洞 题目 根据网站图片和题目描述的提示&#xff0c;大象是php&#xff0c;蟒蛇是python&#xff0c;说明了这个网站是用python写的 在python中&#xff0c;比较常规的漏洞就是SSTI模板注入 没有思路&#xff0c;先点login和register页面看看 查看源代码 之前…

读论文---On Distillation of Guided Diffusion Models

该论文解决的问题 1 简要描述 2 在之前的工作中存在下述问题 计算过程需要计算: 1 unconditional的unet 2 conditional(w text)的unet 下图展示了计算过程 对应的代码 pipelines-> stable_diffusion-> pipline_stable_diffusion.py-> StableDiffusionPipeling-> 7…

C#在工业自动化领域的应用前景如何?

在2021年&#xff0c;C#与工业自动化已经开始结合&#xff0c;并且这种趋势有望在未来继续发展。C#是一种功能强大的编程语言&#xff0c;其面向对象的特性、跨平台支持以及丰富的类库和工具&#xff0c;使其成为在工业自动化领域应用的有力工具。 我这里刚好有嵌入式、单片机…

微服务系列文章 之 nginx日志格式分析以及修改

如何自定义日志格式&#xff0c;就需要修改nginx日志打印格式 一. 打开终端&#xff0c;登录服务器并输入服务器密码 //ssh 用户名服务器ip ssh root192.168.0.132二. 切换到nginx目录 cd /var/log/nginx/ 三. 查看nginx日志 tail -f access.log 日志说明&#xff1a; //…

Servlet的监听器

Servlet常用的监听器 ServletContextAttributeListener 用来感知ServlerContext对象属性变化&#xff0c;比如添加或删除属性变化 ServletContextListener 用来感知ServlerContext对象的创建和销毁的 ServletRequestListener 可以用来监听感知ServletRequest对象的创建和销毁的…

OLED拼接屏采购指南:如何选择最佳方案?

OLED拼接屏作为一种创新的大屏幕显示设备&#xff0c;正在成为各行各业信息展示和传播的重要工具。 然而&#xff0c;面对市场上众多的品牌和型号&#xff0c;如何选择最佳的OLED拼接屏方案成为一项关键任务。 本文将为您提供一份全面且实用的OLED拼接屏采购指南&#xff0c;…

.NET Native AOT的静态库与动态库

.NET不仅可以使用 C静态库与动态库&#xff0c;也可以将.NET实现的函数导出为C静态库与动态库。在没有Native Aot之前&#xff0c;.NET只能通过P/Invoke享受C/C生态&#xff0c;而在Native Aot之后&#xff0c;不仅可以享受这些生态&#xff0c;还可以开发SDK供其他语言调用。 …

WAIC2023会后记

听了3天WAIC的会&#xff0c; 大开眼界&#xff0c;算是上了堂大课。 本次参会的目的是听听AI企业信息化的想法、理论和实践。以进一步探索可能的业务场景。三天的会结束后&#xff0c;留下深刻印象的有如下几点。 大模型当道 2023这次大会的主题成了大模型&#xff0c;谈的…

基于单片机电子密码锁射频卡识别指纹门禁密码锁系统的设计与实现

功能介绍 通过指纹进行开锁或者是按键输入当前的密码&#xff0c;修改密码&#xff0c;对IC卡可以进行注册&#xff0c;删除。当有RFID卡进入到读卡器的读卡范围内时&#xff0c;则会自动读取卡序列号&#xff0c;单片机根据卡的序列号对卡进行判断。若该卡是有效卡&#xff0c…

RabbitMQ安装

这里写目录标题 简介下载ELANG安装ELang配置环境变量安装RabbitMQ 简介 RabbitMQ 是一个开源的遵循 AMQP 协议实现的基于 Erlang语言编写&#xff0c;**即需要先安装部署Erlang环境再安装RabbitMQ环境。**需加注意的是&#xff0c;读者若不想跟着我的版本号下载安装&#xff0…

MacBook Java开发环境搭建记录

一、Homebrew的镜像设置 对于Java JDK的安装&#xff0c;我们更推荐使用Homebrew来进行安装管理。但Homebrew的curl国外源的下载速度实在是一言难尽&#xff0c;时常还会发生无法访问的情况。 那么我们此时的解决方法就有两种了&#xff0c;第一种便是使用全局的VPN代理进行下载…

让你不再疑惑加水印用什么软件

每个人都有自己的独特创意和作品&#xff0c;而在现今互联网时代&#xff0c;分享和传播作品已成为一种普遍现象。然而&#xff0c;随着互联网的发展&#xff0c;越来越多的作品被人恶意盗用和复制&#xff0c;使得原创作者的权益受到了侵害。为了保护自己的作品&#xff0c;加…

【SpringBoot】从零开始封装自己的starter并且引入到其他项目中使用

从零开始封装自己的starter并且引入到其他项目中使用 简介 本文将介绍如何从零开始封装自己的starter并且引入到其他项目中使用 为什么要自己封装starter&#xff1f; 这样可以对spring以及其他第三方提供的starter做二次封装或者封装一些自己需要的内容提供给其他项目使用&…

MySQL五种约束类型(普通 /自增主键,外键等) + 进阶查询(聚合查询,内 /外连接查询,自连接查询,子查询,合并查询)

文章目录 前言一、五种约束NOT NULL 约束UNIQUE 约束DEFAULT 约束PRIMARY KEY 主键约束(重点)普通主键自增主键 FOREIGN KEY 外键约束(重点) 二、进阶查询聚合查询聚合函数GROUP BY子句HAVING 联合查询笛卡尔积内连接外连接自连接子查询单行子查询&#xff1a;返回一行记录的子…

乔云监控tf卡格式化后数据恢复方法

您有没有使用过乔云牌监控设备呢&#xff1f;它通常里面会放置一个TF卡以存储录像&#xff0c;而TF卡长期高温高速运行&#xff0c;容易产生碎片&#xff0c;因此很多商家会建议大家一个月进行一次格式化。但是格式化后您有没有后悔过呢&#xff1f;在这个篇文章中&#xff0c;…

【Python】类型注解 ③ ( 使用 # type: 类型 注释方式设置类型注解 | 类型注解是提示性而非强制性 )

文章目录 一、使用 注释语法 设置 类型注解1、使用 注释语法 设置 类型注解语法介绍2、为 基础类型变量 设置 " 类型注解 "3、为 类 的 对象类型 设置 " 类型注解 "4、为 基础容器类型变量 设置 简易 " 类型注解 "5、为 基础容器类型变量 设置 详…

基于深度学习的高精度工人安全帽检测识别系统(PyTorch+Pyside6+YOLOv5模型)

摘要&#xff1a;基于深度学习的高精度工人安全帽检测识别系统可用于日常生活中或野外来检测与定位工人安全帽目标&#xff0c;利用深度学习算法可实现图片、视频、摄像头等方式的工人安全帽目标检测识别&#xff0c;另外支持结果可视化与图片或视频检测结果的导出。本系统采用…

Windows与Linux取证分析

目录 一、电子数据取证基本概念 1.电子取证学 2.常规取证 3.洛卡德物质交换原理 4.电子数据范围 5.电子数据取证的概念和目的 6.电子数据取证过程 二、Linux系统取证 1.基本信息获取 &#xff08;1&#xff09;获取系统基础信息 &#xff08;2&#xff09;用户/用户…

共筑开源新长城 龙蜥社区走进开放原子校源行-清华大学站

6 月 28 日&#xff0c;以“聚缘于校&#xff0c;开源共行”为主题的 2023 年开放原子校源行活动在清华大学成功举行。本次活动由开放原子开源基金会和清华大学共同主办&#xff0c;来自各行业的 22 位大咖共聚校园共话开源。龙蜥社区技术专家边子政受邀进行技术分享&#xff0…