关于c#中异步async和await的理解
之前给大家介绍了所谓异步编程的用法,但是没有细致的理解到,今天想和大家一起探讨一下;
前文:
C#笔记14 异步编程Async,await,task类-CSDN博客
异步的起初
应用程序会启动一个进程,一个进程可以有很多线程。
如果一个线程,我们给他命名为主线程。
这个线程如果一直往下走,只有一条线,这就是单线程。
还是这个线程,如果它运行的途中创建了新的小伙伴去执行其他任务,这就是多线程。
现在我们的主线程正在做着自己的事情类似于展示一个界面之类的,此时创建一个线程去后台执行其他任务,主线程不去管它,这就是异步。
所以多线程的起初就是异步的。
同步的出现
现在,主线程创建了两个小弟,两个小弟功能差不多,这两个小弟为了抢占一个资源,打起来了。这可不行对吧,于是我们就设立各种同步机制和同步锁,控制他们学会等待。
等待的方式各不相同,但是毫无疑问,线程间互相有了约束和阻塞。
到这里其实我们想做的事情已经基本完成了。
线程各司其职遇到资源就进行同步机制的等待和唤醒操作。
但是还是会有问题,比如多线程的管理,小弟太多了,根本管不过来,小弟之间使用资源的调度原则不够公平等等。当然了,这要求程序员的管理和操作系统的调度配合。
除此之外也发现管理多线程的方式不够先进:
管理的困难
主线程是老大,今天派小弟出去办事,小弟办事之后,确实办完了,但是主线程不知道小弟已经办完了,这时候是不是有小伙伴要想到C#中的委托和事件了?
这样就可以让小弟通知老大哥自己做好了,老大哥订阅了小弟的这个事件,这样就能在小弟完成事件的时候执行对应的方法了。
但是每一个小弟都这样,老大哥要手动管理这些事件,就好像老大哥每天都得坐在办公室听汇报了一样,尤其是管理线程的我们觉得很烦,这个组织太杂乱了!
尤其是什么情况?需要反复派出小弟去干活的时候,比如密集的io环境,我们还要和每个小老弟都约定一个事件,啥时候通知老大哥。
尤其是线程一多,老大哥虽然不迷糊但是老大哥也很烦,但是我们程序员,也就是负责真正管理小弟的人迷糊了。这可怎么办?
此时:
如果不派小弟去干,自己干,老大哥自己的事情就做不好了。(阻塞)
如果派出小弟,让小弟自己干自己的,老大又不知道到底干的什么情况了,就算小弟已经把结果搞出来了,已经通过什么形式提交了也不知道。(多线程异步)
如果手动告诉小弟怎么通知老大,这下倒是可以了,但是咱们秘书(程序员)可怜了,天天就负责管理每个小弟,告诉小弟在哪告诉老大,然后记下老大小弟给的数据怎么处理,用什么方法处理。(事件通知的多线程)
到这我们秘书就想到一个方法减轻自己的工作量。将社团改组,大哥和小弟都不是按所谓线程来做事了,而是新的机制或者说不同的任务处理者Task。
新的处理异步的方法
async和await出场!
async:用于标记一个方法是异步的,告诉编译器这个方法会有异步操作。该方法仍然可以在线程池中调度执行任务,但这个并不由 async 本身控制。
await:用于等待异步操作完成,而不会阻塞当前线程。它只会让出控制权,让当前线程去做其他事情,当操作完成时,再继续执行后续代码。
async标记一个事情,告诉老大和小弟,这个事情是异步的,这个事情要让小弟去干,不能影响老大哥工作。所以这个方法使用之后会立刻返回一个任务的引用作为结果,等到事情办完了这个结果才会被填充为指定的值。
await专门用来调用一个需要耗时间的操作,调用之后会让出控制权,等到再次获取控制权也就是后面等待的操作有结果的时候,如果异步方法有返回值的话,await还会自动把值从结果里拿出来给指定的对象。
老大哥调用异步方法就像派出一个小弟,task作为方法的返回值就像小弟给大哥留的纸条,等到小弟任务完成了,这个纸条上就会出现结果。这中间呢纸条就放在这里,。
await是逻辑上的等待这个结果,如果这个结果没有出现,后面的逻辑就不会执行。
意思是老大虽然后面有些事要等待这个事情,不代表老大就抛下自己手上的事情了,实际上老大还是在干活的。
你会发现小弟中间也会有一些await操作。
老大哥一调用这个事情啊,可以使用task,意思就是老大哥派出了这个小弟,但是自己没有去干奥,这个小东西就是小弟留给老大的小纸条,
await就是小弟告诉老大:“好,现在该到这里了,我得等某个任务完成了才能继续。
意思是什么?小弟办事也不是说立刻就办完了。也就是我们的方法内部也许还有耗时间的更具体的操作,比如老大让小弟读写一批文件,小弟可能要一个个文件读写,这就是小弟给老大的纸条。
await 就像说:“等这个任务做完了,再通知我,我再继续往下走。”
所以,await 的作用是让程序在某个任务完成之前,不阻塞其他操作。它并不会傻傻等着,而是会继续处理其他的事情,等到这个耗时操作完成后,再回到你指定的位置继续执行。
using System;
using System.Net.Http;
using System.Threading.Tasks;class Program
{static async Task Main(string[] args){Console.WriteLine($"{DateTime.Now:HH:mm:ss} - 大哥:开始做事,我让小弟去下载文件");// 大哥派小弟去干下载文件的活Task downloadTask = 小弟去下载文件Async("http://example.com/largefile");// 大哥自己继续干活for (int i = 0; i < 10; i++){Console.WriteLine($"{DateTime.Now:HH:mm:ss} - 大哥:我在忙别的事... {i}");await Task.Delay(1000); // 模拟大哥处理别的事情需要一些时间}// 等小弟把下载任务做完await downloadTask;Console.WriteLine($"{DateTime.Now:HH:mm:ss} - 大哥:小弟终于把文件下载完了,事情都做完了,收工!");}// 小弟去下载文件,过程可能很久static async Task 小弟去下载文件Async(string url){Console.WriteLine($"{DateTime.Now:HH:mm:ss} - 小弟:开始下载文件...");using (HttpClient client = new HttpClient()){// 模拟下载文件的耗时操作await Task.Delay(5000); // 假装下载需要5秒钟Console.WriteLine($"{DateTime.Now:HH:mm:ss} - 小弟:文件下载完了!");}}
}
10:00:00 - 大哥:开始做事,我让小弟去下载文件
10:00:00 - 小弟:开始下载文件...
10:00:00 - 大哥:我在忙别的事... 0
10:00:01 - 大哥:我在忙别的事... 1
10:00:02 - 大哥:我在忙别的事... 2
10:00:03 - 大哥:我在忙别的事... 3
10:00:04 - 大哥:我在忙别的事... 4
10:00:05 - 小弟:文件下载完了!
10:00:05 - 大哥:我在忙别的事... 5
10:00:06 - 大哥:我在忙别的事... 6
10:00:07 - 大哥:我在忙别的事... 7
10:00:08 - 大哥:我在忙别的事... 8
10:00:09 - 大哥:我在忙别的事... 9
10:00:09 - 大哥:小弟终于把文件下载完了,事情都做完了,收工!
可以看出来,大哥在派出小弟之后自己还在做事,事实上小弟此时也正在下载文件。(注意,这里的小弟不是某个特定的我们管理的线程,而是被我们的系统指派的线程池甚至就是操作系统在做。)
大哥的await就是等小弟。
小弟的await就是小弟等小弟。
注意,await不会让后面的代码提前执行,反而是会就像顺序执行一样来执行。
但是它这种等待和我们之前线程的等待又不太一样,因为这种等待是代码让出控制权给其他方法去执行。
异步方法之间的依赖
小弟之间也存在依赖的时候呢,就可以像下面一样了。
using System;
using System.Threading.Tasks;class Program
{static async Task Main(string[] args){Console.WriteLine($"{DateTime.Now:HH:mm:ss} - 老大哥:开始派小弟A去下载文件");// 小弟A开始下载文件,小弟B等他下载完Task 小弟A的任务 = 小弟A去下载文件Async();Task 小弟B的任务 = 小弟B等小弟A再处理文件Async(小弟A的任务);Console.WriteLine($"{DateTime.Now:HH:mm:ss} - 老大哥:我先干点其他的事...");// 等两个任务都完成await Task.WhenAll(小弟A的任务, 小弟B的任务);Console.WriteLine($"{DateTime.Now:HH:mm:ss} - 老大哥:小弟们都完成了,我收工!");}static async Task 小弟A去下载文件Async(){Console.WriteLine($"{DateTime.Now:HH:mm:ss} - 小弟A:开始下载文件...");await Task.Delay(3000); // 模拟耗时的下载过程Console.WriteLine($"{DateTime.Now:HH:mm:ss} - 小弟A:文件下载完了!");}static async Task 小弟B等小弟A再处理文件Async(Task 小弟A的任务){Console.WriteLine($"{DateTime.Now:HH:mm:ss} - 小弟B:我得等小弟A下载完才能干活...");await 小弟A的任务; // 等待小弟A的任务完成Console.WriteLine($"{DateTime.Now:HH:mm:ss} - 小弟B:现在小弟A下载完了,我开始处理文件...");await Task.Delay(2000); // 模拟文件处理时间Console.WriteLine($"{DateTime.Now:HH:mm:ss} - 小弟B:文件处理完了!");}
}
事实上,任务机制可以让我们像写同步代码一样来写一些需要异步的操作。
同样的代码逻辑,实际的执行上就会不同。
这和传统线程管理的方式不同,避免了管理线程和事件订阅以及那种嵌套回调函数的麻烦。
这只是当下我浅薄的理解,如果我说的有错,请帮我指出,感谢。
相关文章:

关于c#中异步async和await的理解
之前给大家介绍了所谓异步编程的用法,但是没有细致的理解到,今天想和大家一起探讨一下; 前文: C#笔记14 异步编程Async,await,task类-CSDN博客 异步的起初 应用程序会启动一个进程,一个进程可以有很多…...

mysql等保数据库命令
mysql数据库命令 默认安装位置:C:\Program Files\MySQL\MySQL Server 8.0\bin select version() from dual; desc mysql.user; 查看表中有哪些列 1、SELECT user, host, authentication_string, account_locked ,password_lifetime FROM mysql.user; 查询用户表…...

云平台在大规模设备管理和数据分析中的作用
在当代数字化转型的浪潮中,云平台作为信息技术基础设施的核心组件,扮演着无可替代的角色,尤其在大规模设备管理和数据分析领域,其重要性和影响力日益凸显。本文旨在深入探讨云平台如何通过其独特的优势,促进数据的高效…...

数据结构-树和二叉树
树 和 二叉树 1.树的概念 树 tree 是n(n>0)个节点的有限集 在任意的一个非空树中 (1)有且仅有一个特定的被称为 根(root) 的节点 (2)当n>1时, 其余的节点可分为m(m>0)个互不相交的有限集T1, T2, T3, .... …...

树和二叉树的概念以及结构
一起加油学数据结构 目录 树的概念以及结构 树的概念 树的相关概念 树的表示 二叉树的概念以及结构 二叉树的概念 特殊的二叉树 二叉树的性质 二叉树的存储结构 树的概念以及结构 树的概念 树是一种非线性的数据结构,它是由n(n>0)…...

c语言习题
第三章 数据类型、运算符与表达式 一 单项选择题 1.下面四个选项中,均不是 c 语言关键字的选项是( )。 A) define IF Type B) getc char printf C) include scanf case D…...

Python 低层多线程接口_thread的用法
_thread是python标准库中的一个低层多线程API,可以在进程中启动线程来处理任务,并且提供了简单的锁机制来控制共享资源的同步访问。本文就_thread模块的用法和特性做个简单的演示。 文章目录 一、进程和线程的区别二、_thread模块的用法2.1 派生线程2.2…...

flutter基础 --dart语法学习
由于想要写一款性能较好,但是又可以一套代码多个平台运行的客户端app,所以选择了flutter 就去看了官方文档,大体发现flutter使用的dart语言和java和js差不多,感觉就是缝合怪。 Dart 是一种面向对象的编程语言,语法上与 Java、JavaScript 等语言有一些相似之处&…...

新手必看:一步步教你绑定常见邮箱到第三方应用(如何绑定QQ、163、Hotmail、Gmail等邮箱)
文章目录 📖 介绍 📖🏡 演示环境 🏡📒 邮箱绑定 📒📫 QQ邮箱📫 163邮箱📫 Hotmail邮箱📫 Gmail邮箱📫 Yahoo邮箱📫 iCloud邮箱📫 其他邮箱⚓️ 相关链接 ⚓️📖 介绍 📖 你是否曾经为绑定第三方邮箱而感到困惑?你不是一个人!许多人在尝试将QQ邮…...

mac 怎么查看CPU核数
在 macOS 系统中,可以通过以下几种方法查看 CPU 核心数: 1. 使用“关于本机”查看 点击左上角的苹果图标()。选择“关于本机”。在弹出的窗口中,系统会显示 Mac 的基本信息,包括 CPU 的类型和核心数。比…...

Vue生命周期;Vue路由配置;vue网络请求;vue跨域处理
一,Vue生命周期 <template><div > <h1 click"changeText">{{ info }}</h1></div> </template><script> export default {name: HelloWorld,data(){return{info:"介绍组件生命周期"}},methods:{chang…...

汽车电子电气架构从12V提升至48V,带来那些好处? 包括那些改变?
标签: 汽车电子电气架构; 从12V提升至48V; 汽车电子电气架构从12V提升至48V,带来那些好处? 包括那些改变? 将传统汽车的电子电气架构电压从12V提升至48V,既有显著的优势,也需要对车…...

springboot实战学习笔记(2)
目录 1、手动创建springboot工程,选择Maven构建。 2、Maven生成的,可能需要再main目录下new一个resources目录,再在其下目录new一个配置文件。 3、 pom文件中让当前的工程继承父工程依赖:、删去无用依赖。 4、引入后端环境所需要的…...

Python练习宝典:Day 1 - 选择题 - 基础知识
目录 一、踏上Python之旅二、Python语言基础三、流程控制语句四、序列的应用 一、踏上Python之旅 1.想要输出 I Love Python,应该使用()函数。 A.printf() B.print() C.println() D.Print()2.Python安装成功的标志是在控制台(终端)输入python/python3后,命令提示符变为: A.&…...

macOS平台(intel)编译MAVSDK安卓平台SO库
1.下载MAVSDK: git clone https://github.com/mavlink/MAVSDK.git --recursive 2.编译liblzma 修改CMakeLists.txt文件增加C与CXX指令-fPIC set(CMAKE_C_FLAGS "-fPIC ${CMAKE_C_FLAGS}") set(CMAKE_CXX_FLAGS "-fPIC ${CMAKE_CXX_FLAGS}") 修改如下:…...

set的相关函数(3)
3.删除 //删除 /* int main() {set<int> s;s.insert({ 2,4,5,2,6,8,10,15 });for (auto e : s){cout << e << " ";}cout << endl;//删除最小的元素就删除排序后的首元素s.erase(s.begin());for (auto e : s){cout << e << "…...

Python MongoDB
MongoDB 是目前最流行的 NoSQL 数据库之一,使用的数据类型 BSON(类似 JSON)。 MongoDB 数据库安装与介绍可以查看我们的 MongoDB 教程。 PyMongo Python 要连接 MongoDB 需要 MongoDB 驱动,这里我们使用 PyMongo 驱动来连接。 …...

安国U盘量产工具系列下载地址
来源地址(访问需要科学工具):AlcorMP (Последняя версия ALCOR U2 MP v23.08.07.00.H) – [USBDev.ru] 版本列表: AlcorMP(最新版本的 ALCOR U2 MP v23.08.07.00.H) AlcorMP是在Alcor Mic…...

2024年最新版Vue3学习笔记
本篇文章是记录来自尚硅谷禹神2023年课程的学习笔记,不得不说禹神讲的是真的超级棒! 文章目录 创建Vue3工程main.ts文件解析初始化项目写一个简单的效果 Vue3核心语法setup函数setup和选项式的区别setup语法糖指定组件名称 响应式数据ref函数定义基本类…...

FX5 CPU模块和以太网模块的以太网通信功能
FX5 CPU模块和以太网模块的以太网通信功能的概要如下所示。 CPU模块的内置以太网端口的通信规格如下所示。 1、与MELSOFT的直接连接 不使用集线器,用1根以太网电缆直接连接以太网搭载模块与工程工具(GX Torks3)。无需设定IP地址,仅连接目标指定即可进行…...

【结构型】树形结构的应用王者,组合模式
目录 一、组合模式1、组合模式是什么?2、组合模式的主要参与者: 二、优化案例:文件系统1、不使用组合模式2、通过组合模式优化上面代码优化点: 三、使用组合模式有哪些优势1、统一接口,简化客户端代码2、递归结构处理方…...

C++——求3*3矩阵对角元素之和。
没注释的源代码 #include <iostream> using namespace std; int main() { int a[3][3],i,j,sum0; cout<<"请输入a组中的元素:"<<endl; for(i0;i<2;i) { for(j0;j<2;j) { cin>>a[i][j]…...

nodejs基于vue电子产品商城销售网站的设计与实现 _bugfu
目录 技术栈具体实现截图系统设计思路技术可行性nodejs类核心代码部分展示可行性论证研究方法解决的思路Express框架介绍源码获取/联系我 技术栈 该系统将采用B/S结构模式,开发软件有很多种可以用,本次开发用到的软件是vscode,用到的数据库是…...

GO Ants 学习
文章目录 主要特性安装基本用法1. 创建协程池并提交任务2. 带返回值的任务提交3. 自定义协程池的参数4. 获取协程池状态 应用场景优势资源释放性能对比总结 ants 是一个高性能的 Go 语言协程池库,专注于有效地管理 Go 协程的数量。它通过复用协程减少了创建和销毁协…...

Scikit-learn (`sklearn`) 教程
Scikit-learn (sklearn) 教程 Scikit-learn 是 Python 中最流行的机器学习库之一,提供了丰富的机器学习算法、数据预处理工具以及模型评估方法,广泛应用于分类、回归、聚类和降维等任务。 在本教程中,我们将介绍如何使用 Scikit-learn 进行…...

【计网】从零开始掌握序列化 --- JSON实现协议 + 设计 传输\会话\应用 三层结构
唯有梦想才配让你不安, 唯有行动才能解除你的不安。 --- 卢思浩 --- 从零开始掌握序列化 1 知识回顾2 序列化与编写协议2.1 使用Json进行序列化2.2 编写协议 3 封装IOService4 应用层 --- 网络计算器5 总结 1 知识回顾 上一篇文章我们讲解了协议的本质是双方能够…...

Qt 模型视图(四):代理类QAbstractItemDelegate
文章目录 Qt 模型视图(四):代理类QAbstractItemDelegate1.基本概念1.1.使用现有代理1.2.一个简单的代理 2.提供编辑器3.向模型提交数据4.更新编辑器的几何图形5.编辑提示 Qt 模型视图(四):代理类QAbstractItemDelegate 模型/视图结构是一种将数据存储和界面展示分离的编程方…...

django+vue
1. diango 只能加载静态js,和flask一样 2. 关于如何利用vue创建web,请查看flask vue-CSDN博客 3. 安装django pip install django 4. 创建新项目 django-admin startproject myproject 5.django 中可以包含多个app 5.1 创建一个app cd myprojec…...

HCIA--实验十七:EASY IP的NAT实现
一、实验内容 1.需求/要求: 通过一台PC,一台交换机,两台路由器来成功实现内网访问外网。理解NAT的转换机制。 二、实验过程 1.拓扑图: 2.步骤: 1.PC1配置ip地址及网关: 2.AR1接口配置ip地址࿱…...

彻底解决:QSqlDatabase: QMYSQL driver not loaded
具体错误 QSqlDatabase: QMYSQL driver not loaded QSqlDatabase: available drivers: QSQLITE QMIMER QMARIADB QMYSQL QODBC QPSQL 检查驱动 根据不同安装目录而不同: D:\Qt\6.7.2\mingw_64\plugins\sqldrivers 编译驱动 如果没有,需要自行编译&…...