分享好友 最新动态首页 最新动态分类 切换频道
c#: 异步代码是如何解决高并发问题的?async/await、Task、IOCP/epoll
2024-12-27 02:18

环境

  • window 10
  • centos 8.2
  • .netframework
  • .netcore

参考
《MSDN:异步编程模型 (APM)》
《MSDN:异步编程模式》
《MSDN:I/o 完成端口》
《Linux下的I/O复用与epoll详解》
《浅谈async、await关键字 => 深谈async、await关键字》
《重新认识 async/await 语法糖》

和同步相反,指在处理任务时可以不用等待任务结果而继续向后执行,这样就能减少等待耗费的时间,从而达到高效利用服务器资源的效果。

异步的目的:合理规划任务的执行顺序,避免不必要的任务等待,减少服务器资源消耗,从而在服务器性能以及用户的交互体验上达到满意的效果。

多线程和异步的区别
多线程是异步的主要实现方式,事实上几乎所有的异步都有多线程的影子。但异步是从任务执行效果的角度看的,而多线程是现代计算机的一个基础功能。

同步的问题根源:阻塞当前线程、占用CPU和内存资源。

  • 多个代码块的串行:将代码块并行

     
  • winform界面的按钮事件:耗时代码采用异步调用

     

如果传统web服务器对网卡的读写采用同步调用的话,在高并发下很容易卡死,同样,如果我们程序中同步读写数据库,在高并发下也很容易卡死。

linux中的epoll(事件-响应)模型就是为了解决这种问题出现的。在window中叫做IOCP(I/O Completion Ports,也叫作完成端口)。

下面用一个场景类比epoll和IOCP的处理模型(epoll和IOCP在原理上是相同的)。

场景是这样的

有一个小镇,里面的人们要去镇外采购食物(表示:客户端向服务器发起请求,需要经过一条不宽的河流(表示:服务器的CPU、内存等资源有限,河流的管理者负责组织船只运输往返的人们(表示:CPU在时间切片内调度线程,每一个船只表示一个线程)。

改革后的方案也称之为epoll模型(linux,当然在window中叫做IOCP。

通过上面的故事,我们知道了epoll的机制,显然它是高并发下最有效的请求响应模型。
然而,当epoll出现之前,linux为了解决高并发问题还制定了select和poll模型,不过它们两个都有着很明显的缺点,可以认为它们是残次品吧。
但是,在并发程度不高的情况下,select和poll的性能和epoll也不相上下,所以nginx也是支持select和poll的)。

IOCP的原理和epoll一致。不过仍有些不同

在.net framewok时代,线程池中的线程被分为两类,和。两者的区别是 “完成端口线程专门为I/O设备读写完成后回调使用的。”

对于为什么要把线程人为的划分为两类,我还没找到准确的答案,大概是当时的设计者担心线程池内的线程被用光而导致没有线程用于回调,进而导致无限等待了吧。。。

在.net core时代,设计者有意弱化IOCP的概念,即:不想再区分和了。所以在.net framework中的I/O回调代码中,我们能明显看到可用数量的减少,但是在.net core中同样的I/O回调代码下,我们仅能观察到的可用数量减少,而的可用数量始终保持不变。

另外,当我们代码中强制调用线程池中的时(.net core,window下能观察到的可用数量减少,但是在linux下抛出异常,测试代码如下

 
 

centos下运行报错

 

那么,IOCP的概念究竟应不应该去掉呢?有没有发挥到它的作用呢
我认为:IOCP可以去掉,发挥的作用有限。

试想一下,I/O设备回调用的是,如果回调中再发起I/O读写,那么回调就又使用,这样下去,我们只要发起一次回调,之后的代码都将运行在上了。。。
听起来很恐怖的样子,不过我没有试验,不知道真正效果如何。

另外,epoll中也没有专门给I/O回调配置线程不也运行的挺好的嘛。

实际上,我认为,只要代码中涉及到I/O读写的代码调用处都使用异步的话应对高并发就没有问题了。不用再去区分什么和了,反正代码运行的都很快,但凡慢一点的都交给I/O回调了,不用担心I/O回调时没有线程可用。

异步的作用是将串行的代码改成并行的,当代码并行后,当前线程是释放回线程池还是阻塞以等待异步执行完毕,可以将异步作用分为两个

  • 异步后,当前线程不发生阻塞,释放回线程池,这适合高并发编程
  • 异步后,当前线程需要等待异步执行完毕,在并发不高的情况下,这没什么问题
  • 在.net 1.0的时候提出了

    以IAsyncResult接口为核心,支持异步的接口命名规则为: BeginXXXX、EndXXXX

  • 在net 2.0的时候提出了

    支持异步的方法以XXXXAsync命名,外加XXXXCompleted事件

  • 在.net 4.0的时候提出了

    是我们现在常用的task模式,await/async task

1. 异步编程模型(APM)

当我们调用BeginXXXX异步调用时,虽然没有立刻返回结果,但是给了我们一个信物(就是,凭借这个信物,我们可以轮训是否异步完成,或者直接阻塞当前线程以等待异步结束)。

下面是模拟的APM模式代码

 
 

2. 基于事件实现的异步编程(EAP)

根据上面介绍,使用APM方式已经可以实现异步编程了,但是使用起来比较麻烦,因为要想不阻塞当前线程就必须利用回调,而回调后会发生线程切换,这对Winform线程来说是致命的(默认,winform中只允许UI线程访问控件)。
所以,基于事件的异步编程应运而生,它不仅简化了异步代码的编写还能让回调代码运行在主线程中。
典型的组件示例是,新建一个winform工程,在窗体上拖拽一个Lable标签、一个PictureBox控件、一个Button按钮,代码如下

 
 

除了PictureBox控件,最能代表EAP模型的还有组件,它的示例MSDN上已经有详细的介绍,请参照:《MSDN:BackgroundWorker 类》

3. 基于任务实现的异步编程(TAP)

虽然有了APM和EPM两种异步模型,但在高并发时编写代码还是有难度

  • 像APM一样多层嵌套回调会形成回调地狱,不好看也不易阅读
  • EPM的事件触发调用并不适合高并发场景

从上面的分析中,我们知道:具有async/await修饰的Task代码块会被自动切割,这里就来看一下它是怎么被切割的。

以下面代码示例

 
 

为了能更好的阅读,我们将代码拷贝到VS中,剔除掉代码中的<>符号并修复掉其他报错信息,最终如下

 

这里可以自行调试运行一下,观察下运行的顺序就明白了vs是怎么将切分的代码块按顺序运行的。
主要逻辑如下

  • 第一步:创建状态机,继承IAsyncStateMachine,设置其状态为-1
  • 第二步:执行状态机的MoveNext()方法,因为状态为-1,所以执行了切割的第一块代码,并使用Task开启了第二块代码的调用
  • 第三步:第二块代码调用完成后,状态机构造器设置状态机状态为0,并调用状态机的MoveNext()方法
  • 第四步:执行状态机的MoveNext()方法,因为状态为0,所以使用Task开启了第三块代码的调用
  • 第五步:第三块代码调用完成后,状态机构造器设置状态机状态为1,并调用状态机的MoveNext()方法
  • 第六步:执行状态机的MoveNext()方法,因为状态为1,所以使用Task开启了第四块代码的调用
  • 第七步:第四块代码调用完成后,状态机构造器设置状态机状态为2,并调用状态机的MoveNext()方法
  • 第八步:执行状态机的MoveNext()方法,因为状态为2,所以直接执行了第五块代码

从分析过程可以看出,vs对async/await标记的方法生成了状态机,并按照await位置将方法中的代码块切割,最后使用状态机的回调机制按顺序执行代码,达到了最终的效果。

如果让我们自己优化上面的代码,我们会怎么生成呢
最简单的写法如下

 
 

在书写异步代码时,我们经常看到如下代码
await httpClient.GetAsync(“https://www.baidu.com”).ConfigureAwait(false);
这里的的作用是什么呢

:告诉task运行时不捕获当前的上下文。也可以简单的理解为:告诉Task调度程序,后面的代码没必要在原来的线程上运行。这就等于解放了Task调度器的手脚,Task调度时将更加迅速,因为调度器没必要等待原有线程是否空闲。

以下面代码分别在.net core3.1和.net framework平台下运行的效果说明其差别

 
 
 

关于的更多解释:《理解C#中的ExecutionContext vs SynchronizationContext》

最新文章
支付宝逾期多久会转第三方的解决方法是什么
在当今的互联网时代支付宝作为我国领先的第三方支付平台为广大客户提供了便捷的支付服务。在利用支付宝的期间逾期还款难题时有发生。本文将围绕支付宝逾期多久会转第三方的应对方法实施探讨帮助客户更好地熟悉逾期还款的后续影响及应对策略
苹果6肿么戴图片 截屏快捷键
苹果6sp怎么截屏快捷键1、快捷键截屏:同时按下iPhone6S Plus【电源键】和【Home键】即可。2、辅助触控截屏:进入系统设置菜单,然后依次点击【辅助功能】-【触控】-【辅助触控】,打开【辅助触控】功能;在【辅助触控中】将【轻点两下】设
萨宝智能锁快速售后24小时人工400-(问题解决) - 农业 - 百科知识-蓝心网
萨宝智能锁售后24小时维修服务热线:400-658-8618。萨宝智能锁全市各区售后服务点热线号码。☎:400-658-8618萨宝智能锁售后服务,秉承“诚信为本、客户至上”的服务态度和“以客户为中心”的服务指导思想,不仅真诚地为用户提供先进、高质
Red Giant Magic Bullet Suite For Mac v2024.0.1 红巨星调色插件
对于M1/M2/M3/M4芯片的电脑,如果软件官方未兼容 M1/M2/M3/M4,可以使用 Rosetta2 转译运行。在Apple Silicon ARM Mac电脑上安装Rosetta 2 运行intel应用苹果自家的M1和M2/M3/M4芯片都是ARM架构,所以M1和M2/M3/M4是完全通用的,未来就算有
罗定终于等到了!会“自动驾驶”的AI手机亮相天润广场!
笃行致远 遇见未来罗定荣耀销服一体店正式亮相啦!罗定天润广场 1F12月14日 | 试营业中12月15日 | 盛大开业新店开业,三重大礼等你来拿!One·荣耀简介·- HONOR -荣耀(HONOR),成立于2013年,荣耀是全球领先智能终端提供商,致力于构建
用AI生成超逼真美女写真:搜狐简单AI完全指南
在这个时代,科技的进步让我们很好地记录生活的点滴,而AI技术的崛起更是让每一个人都能成为创作者。你是否曾想过,一张栩栩如生的美女写真,可以只通过几次点击就能生成?让我们一起深入探讨一下AI生成美女写真背后的技术,以及如何使用这
抖音直播时没人气怎么办,如何提高直播间热度?
1、请求熟人亲朋好友、同事、同学、家人,你能够找到的人,都拉到你的直播间来。让他们来帮忙增加你直播间的基础人气。2、小号协助小号是我们能自己控制的直播间在线人数,可以避免观众进来后没人评论的尴尬。开启小号后可以在评论区留言增
从机器幻觉到智能幻觉
机器幻觉与智能幻觉主要是关于人工智能(AI)系统在处理信息和生成输出时,可能会产生的错误认知或“幻觉”现象。1. 机器幻觉在早期的计算机科学中,“机器幻觉”通常指的是计算机在进行数据处理时,出现了错误的输出或意外的结果。这类“
黑神话,悟空游戏帧数优化提升技巧详解
摘要:本文介绍了提升《黑神话:悟空》游戏帧数的方法。对于想要优化游戏体验的玩家来说,提高帧数是一个重要的目标。文章可能涵盖了调整游戏设置、升级硬件配置、关闭不必要的后台程序等多种方法,旨在帮助玩家减少画面卡顿,提升游戏流畅
谷歌推广效果好吗?为什么要选择谷歌推广?
谷歌推广效果好吗?全球90%流量来自谷歌,因此这个问题的答案是显而易见的。google流量是主线,不管你做批发还是零售,都要靠google。但是不管什么推广渠道还是需要推广方法到位才能起到一定的效果。 谷歌推广主要有两种模式:一种是Google
相关文章
推荐文章
发表评论
0评