.NET中的异步编程(一):异步编程的原因

开发 后端
随着微软在2010年的PDC上发布了Visual Studio Async CTP,大大降低了异步编程的难度,但是对于同步代发来说异步的代码还是不好写,但为什么还需要去编写异步的代码呢。

       微软在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操作非常多的服务来说,所获得的益处是不可估量的。

总结

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

【编辑推荐】

  1. .Net reflector两款神器 Deblector和reflexil
  2. VS.NET 2010已经发布了beta2版本 新功能
  3. ASP.NET MVC 3 新特性全解析
  4. ASP.NET站点构建之减少不必要的请求

 

责任编辑:佚名 来源: 博客园
相关推荐

2011-02-22 09:09:21

.NETAsync CTP异步

2011-02-24 12:53:51

.NET异步传统

2013-04-01 15:38:54

异步编程异步编程模型

2013-04-01 15:25:41

异步编程异步EMP

2017-08-02 15:00:12

PythonAsyncio异步编程

2017-05-05 08:44:24

PythonAsyncio异步编程

2024-06-04 15:56:48

Task​.NET异步编程

2015-11-02 09:43:25

ASP.NET异步编程

2020-10-15 13:29:57

javascript

2024-04-18 08:20:27

Java 8编程工具

2021-08-02 11:13:28

人工智能机器学习技术

2021-12-10 07:47:30

Javascript异步编程

2014-07-15 10:08:42

异步编程In .NET

2017-07-13 12:12:19

前端JavaScript异步编程

2016-09-07 20:43:36

Javascript异步编程

2015-04-22 10:50:18

JavascriptJavascript异

2014-05-23 10:12:20

Javascript异步编程

2023-01-12 11:23:11

Promise异步编程

2012-06-14 13:40:04

JavaScript

2011-11-11 15:47:22

JavaScript
点赞
收藏

51CTO技术栈公众号