在2010年的PDC上,微软发布了Visual Studio Async CTP,大大地降低了异步编程的难度,让我们可以像写同步的方法那样去编写异步代码。Async CTP也在社区里掀起了不小的波澜。在这之后,我也学习了一段时间,这个系列会将这段时间的学习作个梳理。

好了,下面进入本文的正题。

为什么需要异步编程

既然同步的写法更自然简单,异步的代码(传统的)不好写,还容易出错,那我们为什么需要去编写异步的代码呢?微软还要费这么大劲投入对Async CTP的开发呢?这其中肯定有一些原因。

快速响应的用户界面

作为电脑的资深用户,我们肯定有多次“漏斗式鼠标”,“转圈式鼠标”的体验吧。点击一个按钮,然后鼠标就在那儿不停的转圈,再在界面上点两下,界面变灰,标题栏上出现“没有响应”。然后我们束手无策,性子好点的就在那儿等待一会儿,看看能不能恢复过来;性子不好的就打开任务管理器杀掉进程,杀掉进程容易,但有可能会破坏重要数据。

那造成这种情况到底是什么原因呢?概括成一句话就是:耗时的操作阻塞了UI线程,造成UI线程不能响应用户操作。关于更底层的原因请移步我的这篇文章:WinForm二三事(一)消息循环。那么这个时候我们就需要一种机制,在发起耗时操作的请求之后要立即返回,不要阻塞UI线程,让UI线程可以继续响应用用户的操作。然后等耗时操作返回后,通过回调来处理耗时操作返回的结果。下面是在UI上使用同步的方式和异步的方式的示意图:

更高的伸缩性

对于服务器端应用来说,一般都是一个线程处理一个请求。另外一点是,线程的创建和销毁是昂贵的(这一点可以参考《CLR via C#》中Thread Baisc一章的描述),而服务器的资源肯定是有限的;并且,线程创建的越多,线程上下文切换就会变得越频繁。所以,为了创建高可伸缩性的服务,我们必须用最少的线程处理更多的请求,这样不仅能够做到消耗更少的资源(创建更少的线程),而且在应对请求突发增长的情况也很有用处,那么这里非常重要的一点就是不要阻塞线程,让线程池能够高效的工作。而且,在服务端应用中,有非常多的IO操作:数据库访问,磁盘操作,Socket访问等。对于这些IO操作,不属于计算密集型操作,是不需要单独分配一个线程来处理的。

要做到高可伸缩性,异步是一剂良药。假设现在这是一个web应用,当用户的HTTP request到来时,线程池提供一个线程来处理(忽略前面的排队等过程),然后到某一点,我们肯定需要读取磁盘、访问数据库,这个时候我们使用异步的方式,发起IO请求,然后处理HTTP request的线程就可以返回到线程池了,它可以继续处理其他请求,不需要在这里等待IO操作的返回。当IO操作完成之后,会通过回调(具体实现方式请参照后续文章)完成刚才那个HTTP reqeust后续的处理。

下面是使用同步方式和异步方式的示意图:

上图只画出了一个请求,高亮显示的那一段其实是不需要占用线程的,其实这段时间该线程可以返回线程池,然后分配去做其他请求,而数据库返回结果之后,再从线程池里分配一个线程来处理后续操作。这样,如果请求多的话,线程池就会创建更多的线程来处理请求,最后结果大家应该都知道了。

从上图可以看出,开始的时候来自线程池的thread1处理请求,然后发起对数据库的请求,发起操作完毕后,thread1被线程池回收;当数据库将结果返回时线程池选择另外一个线程thread2(有可能是原来的那个线程,如果空闲的话)来处理数据库返回的结果,完成后续的操作。对于IO操作非常多的服务来说,所获得的益处是不可估量的。

在异步之前

前面讲解了适用于异步的应用主要分为两种类型:响应灵敏的界面和可伸缩性良好的服务应用。但是实现异步之前我们还应该思考一些其他的问题。

实现异步的方式有很多,比如常见的创建一个后台线程,将任务委托给这个线程执行,但这种类型的异步并不是所有的都是高效的。创建高可伸缩性的应用的秘诀就是创建更少的线程干更多的活儿,我们目标是没有阻塞。要达到这一点在做一个应用之前我们应该先问自己:我的应用是计算密集型的还是IO密集型的。

对于计算密集型,CPU是主要资源。那什么类型的应用是计算密集型的,比如解方程,排序,压缩,图形图像处理等。对于这类应用无论怎样你都必须占用CPU时间,所以你可以通过创建后台线程的方式来实现异步。

对于IO密集型,IO是主要瓶颈。IO不仅仅是我们常说的读取磁盘文件,像数据库操作、FTP、HTTP等一切网络通信,磁盘访问等都属于IO。当我们进行IO操作时,我们实际上是不需要占用CPU的,比如磁盘访问,一般现代的磁盘驱动器都有自己的控制系统,它自己能够控制寻道等,就相当于磁盘自己有一个小CPU在工作,而我们机器的CPU这个时候就可以解放出来(不用等待,可以干其他的活儿),是不占用的。那么这个时候如果我们能使用异步IO(发起异步IO然后立即返回,当异步IO执行完毕后会通知你)将会对我们的应用的效率带来革命性的影响,因为IO相对于CPU来说是非常非常非常慢速的设备,我们甚至只需要很少的线程就可以处理很多的任务。

创建更少的线程干更多的活儿有什么好处可参见我的这篇笔记。

后记

本文主要从创建响应灵敏的用户界面和创建高可伸缩性的服务应用这两种不同的应用场景来阐释我们为什么需要异步。至于如何进行异步开发在后续的文章我会首先介绍传统的异步和Async CTP以及F#中的Async Workflow。

转载于:https://www.cnblogs.com/yuyijq/archive/2011/02/20/1958925.html

.NET中的异步编程(一)-为什么需要异步相关推荐

  1. python2异步编程_最新Python异步编程详解

    我们都知道对于I/O相关的程序来说,异步编程可以大幅度的提高系统的吞吐量,因为在某个I/O操作的读写过程中,系统可以先去处理其它的操作(通常是其它的I/O操作),那么Python中是如何实现异步编程的 ...

  2. android异步编程,AsyncTask简单的异步编程android 中的实现

    类型:行业软件大小:1.5M语言:中文 评分:5.0 标签: 立即下载 在开发移动客户端的时候往往要使用多线程来进行操作,我们通常会将耗时的操作放在单独的线程执行,避免其占用主线程而给用户带来不好的用 ...

  3. 【Flutter】FutureBuilder 异步编程 ( FutureBuilder 构造方法 | AsyncSnapshot 异步计算 )

    文章目录 一.FutureBuilder 简介 二.FutureBuilder 构造方法 三.AsyncSnapshot 异步计算 四.相关资源 一.FutureBuilder 简介 FutureBu ...

  4. dart系列之:dart中的异步编程

    文章目录 简介 为什么要用异步编程 怎么使用 Future 异步异常处理 在同步函数中调用异步函数 总结 简介 熟悉javascript的朋友应该知道,在ES6中引入了await和async的语法,可 ...

  5. 了解和使用DotNetCore和Blazor中的异步编程

    目录 介绍 您对异步编程了解什么? 那么,什么是异步编程? 我们什么时候应该使用它? 任务.线程.计划.上下文 到底是怎么回事? Asnyc编码模式 命名约定 异步任务模式 任务模式 事件模式 阻塞与 ...

  6. 【JavaScript】同步与异步-异步与并行-异步运行机制-为什么要异步编程-异步与回调-回调地狱-JavaScript中的异步操作

    文章目录 1. 同步与异步 1.1 同步行为synchronous 1.1.1 特点 1.1.2 例子 1.2 异步行为asynchronous 1.2.1 必要性 1.2.2 特点 1.2.3 例子 ...

  7. nodejs笔记-异步编程

    1.函数式编程 1.1高阶函数 函数参数只接受基本数据类型或者对象引用,返回值也是基本数据类型和对象引用. //常规参数传递和返回 function foo(x) {return x; } 复制代码 ...

  8. 写给初学者的JavaScript异步编程和背后思想

    导读: 对于接触JavaScript这门编程语言没有多久的本菜鸡而言,在相当长的一段时间内,我都完全无法理解这门语言中的异步编程,不明白什么叫异步编程以及为什么需要异步编程.为什么顺序执行程序就不行了 ...

  9. Async await 异步编程说明

    希望在编程上有些许提高所以 最近连续2篇博客都在说明多线程和异步编程的使用,异步和多线程之间区别请自行百度,因为理解不是特别透彻就不在叙述以免误导大家,这里写下新研究整理 task  和 await ...

  10. nodejs之async异步编程

    2019独角兽企业重金招聘Python工程师标准>>> 1.什么是异步编程? 异步编程是指由于异步I/O等因素,无法同步获得执行结果时, 在回调函数中进行下一步操作的代码编写风格,常 ...

最新文章

  1. php面向对象静态常量,浅谈PHP面向对象编程(四、类常量和静态成员)
  2. byte数组转字符串_leetcode刷题844比较含退格的字符串(带代码解析,带知识点回顾)...
  3. mysql删除属性_SQL语句处理一些修改、新增、删除、修改属性操作(MySql)
  4. C# 配置文件 自定義結點
  5. mysql语句注意点 2021-05-15
  6. opencv 提取图像线条 霍夫线检测
  7. c语言程序设计报告链表,c语言程序设计报告链表实现学生信息管理.docx
  8. python清理日志脚本_Python日志:如果在程序运行时删除了日志文件,则创建新的日志文件(RotatingFileHandler)...
  9. java web 部署_一步一步将java web项目部署到云服务器
  10. 人肉搜索、人肉语言及人肉程序设计
  11. PS2接口鼠标转换成USB接口接线图
  12. TFS2010新建项目失败
  13. 手机也能拍照扫描?这些拍照扫描app方便又好用
  14. 安装打印机驱动时报错 -536870329 或 1FFFFDB9
  15. 编写.CHM格式的文档
  16. 基于微信小程序的垃圾分类小程序(源码已开源)
  17. P3793礼物和糖果
  18. 舌尖上的区块链——校园食品区块链溯源
  19. css特效实现透明渐变
  20. 愿在以后的日子里,即使单枪匹马也能勇往直前

热门文章

  1. 国土空间适宜性评价与承载力评价之间的逻辑关系是什么?
  2. 基因结构显示服务器,服务器固定结构 Server fixed structure
  3. Ubuntu Docker 安装
  4. Hive 创建表的三种方式
  5. python pow和**_第005篇:Python中的数字
  6. python对abaqus本构二次开发_基于Python的Abaqus二次开发实例讲解
  7. python元类使用场景_Python元类使用简介
  8. MySQL 字符串转in/double类型——CAST/CONVERT函数的用法
  9. 洛谷——P2299 Mzc和体委的争夺战
  10. nefu 519 昨日重现