本文版权归博客园和作者吴双本人共同所有。转载和爬虫必须在显要位置注明出处:http://www.cnblogs.com/tdws

半年前翻译了一系列很糟糕的异步编程文章,用异步的常用语来说:”在将来的某个时间“ 我还会重新翻译Async in C#5.0 http://www.cnblogs.com/tdws/p/5617242.html

 写在前面 

  

异步编程在处理并发方面被使用的越来越多,之所以说上面一句话,是为了区分多线程编程。各位司机都知道,实际上异步编程的核心目标正并发处理。可还是经常有一些让人感到很无奈的说法和问题,比如说,异步编程能提高应用性能吗?他能缩短我处理任务的时间吗?他阻塞线程吗?如果不阻塞线程,断点为什么不继续向下执行,我的哥!线程释放到哪儿去了?我都读书少你别骗我,线程都释放了程序怎么运行?前台我用了Ajax,后台使用Async有必要吗?也许如果作为司机的你看到最后一个问题,你只好摊手┑( ̄Д  ̄)┍。

 多线程场景理解

也许在某些时刻,你想提高应用程序执行速度,尽快拿到一个结果。这个时候,应该选择的绝对不是Async和Task。打个比方说,你和你老婆周末去超市购物,刚一进超市门你发现结账的每条队伍都几十人,于是你用到了多线程,你去排队,一个人一个人的往前走,你老婆在另一头抓紧购物,在你快走到收银台的时候,你老婆来把购物车推给了你,于是你们直接结账回家。虽然这种行为很不文明,但这就是多线程,和异步编程一点关系都没有。

 异步编程场景理解

那异步编程是什么情况,能解决什么问题呢?你和你老婆开了一家面包店,在初期只有你俩为顾客服务。没想到新店开张这么火,每分钟来一个顾客,而烤好一份面包需要两分钟。每来一位顾客你都拿着一片面包去后厨烤箱烤,并且你要和你老婆要花两分钟来等各自的烤箱完成任务。可是你等待的这两分钟,又来了两位顾客,着这样的速度下去,根本不能满足顾客们的需求呀!你已经发现你和你老婆的问题了:那就是你和你老婆这两条线程,都被烤箱花费的时间阻塞了!

你和你老婆为了解决阻塞的问题,又买了两台烤箱,并且为了避免新进顾客没人服务,每当你把面包送进烤箱后,标记其属于哪位顾客后立即返回,准备接待新的顾客,再有顾客光临,立马接待,并将新的面包送进另一个烤箱并标记,并立即返回等待为其他人服务。在面包烤好后,烤箱会以“叮”一声,注意在这一信号到达后,并不是一定要你去后厨烤箱取面包,而是你和你老婆谁不忙谁去取。这样处理后,高并发的顾客量,对你来说就显得得心应手了。你和你老婆做为两条线程,可以不断地以非阻塞的形式(不等烤箱),返回到顾客面前。但是需要注意的是不阻塞的概念,他不是让你的程序继续向下执行。就烤面包而言你的一个烤面包方法是这样的:

1.送入面包到烤箱 2.烤箱处理面包并给你结果 3.拿到面包送到顾客。所以说“不阻塞”的概念,不能让你直接做到第三步。在不阻塞期间,是没有线程在你的这个方法中的,这个方法还是要按照时间等待,等待在未来某个时刻的信号唤醒你或者你老婆,此时该方法恢复执行。所以说程序执行的时间依然不变,得到优化的是处理并发的能力,你店里(服务器)的吞吐量。

 看着代码理解

异步编程应当被适用于IO密集型场景,非CPU计算密集场景。大家知道线程受CPU调度,如果你是四核CPU,那么在你的线程池中,拥有四个线程,进程每个虚拟CPU分配一个线程的时候,性能表现会最棒。既能高效运用CPU,又不用来回切换上下文损耗性能。你想想,CPU密集的场景中,CPU就是要占用你的线程,在这个时候异步编程没有任何用处。然而在IO场景中,文件IO由win32用户模式的API到windows内核模式,在内核模式中操作磁盘驱动程序。这期间,你的线程阻塞在驱动程序的响应中。而异步编程中,你的操作通知到磁盘驱动程序后,线程立即返回而非等待,在将来的某个时刻,驱动程序处理结束,处理结果放入CLR线程池队列中,恢复状态机,线程池中任意线程取出结果,方法继续向下执行。在网络IO中也是如此,只不过驱动程序变成了网络驱动程序。请看如下代码:

public static async Task<string> DoSomeAsync()
{
using (var client = new HttpClient())
{
var result = await client.GetAsync(
"http://stackoverflow.com/questions/37991851/jenkins-configure-page-not-loading-version1-651-3-chrome-browser")
.Result.Content.ReadAsStringAsync();
Console.WriteLine(result);
//做一些其他操作
var res = + ;
//----------------
return "";
}
}

在编译的时候,DosomeAsync会被编译成一个状态机方法,状态机是什么先别管,你可以把它当成一个黑盒子。在遇到GetAsync的时候,在DoSomeAsync中返回一个Task任务对象,并由await在Task对象上传递用于恢复状态机的方法,相当于调用了ContinueWith().这个方法顾名思义,以xxx继续。然后线程从DoSomeAsync中返回。返回后干嘛去了?该线程可以去处理其他事情了。在将来某一时刻,服务器向我们发送了一个相应,网络驱动程序得知请求完毕,恢复该方法继续执行剩下的其他代码。配一张乱糟糟的图

 额外的好处

在GC的垃圾清理执行过程中,应用程序的所有线程都会被挂起,使用异步编程意味着在相同的并发量下,你可以使用更少的线程来完成处理,额外带来的好处就是,所需要清理的线程是更少的。还有一点就是,所使用的线程少了,CPU线程切换也变得更少。

如果我的点滴分享对你有点滴帮助,欢迎点击下方红色按钮关注,我将持续输出分享。也欢迎为我也为你自己点赞。

本文关键字,C# ASP.NET 异步编程 MVC Async await

额外阅读:异步编程最佳实践  https://msdn.microsoft.com/zh-cn/magazine/jj991977.aspx

让我们再为C#异步编程Async正名的更多相关文章

  1. 温故知新,CSharp遇见异步编程(Async/Await),聊聊异步编程最佳做法

    什么是异步编程(Async/Await) Async/Await本质上是通过编译器实现的语法糖,它让我们能够轻松的写出简洁.易懂.易维护的异步代码. Async/Await是C# 5引入的关键字,用以 ...

  2. 异步编程Async/await关键字

    异步编程Async \await 关键字在各编程语言中的发展(出现)纪实. 时间 语言版本 2012.08.15 C#5.0(VS2012) 2015.09.13 Python 3.5 2016.03 ...

  3. 抓住异步编程async/await语法糖的牛鼻子: SynchronizationContext

    长话短说,本文带大家抓住异步编程async/await语法糖的牛鼻子: SynchronizationContext 引言 C#异步编程语法糖async/await,使开发者很容易就能编写异步代码. ...

  4. C#异步编程(async and await)及异步方法同步调用

    1.什么是异步? 异步操作通常用于执行完成时间可能较长的任务,如打开大文件.连接远程计算机或查询数据库=异步操作在主应用程序线程以外的线程中执行.应用程序调用方法异步执行某个操作时,应用程序可在异步方 ...

  5. 异步编程async/await

    什么是异步? 在异步程序中,程序代码不需要按照编写时的顺序严格执行,有时需要一在一个新的线程中运行一部分代码,有时无需创建新的 线程,但是为了更好的利用单个线程的能力,需要改变代码的执行顺序. 进程 ...

  6. C#中的异步编程Async 和 Await

    谈到C#中的异步编程,离不开Async和Await关键字 谈到异步编程,首先我们就要明白到底什么是异步编程. 平时我们的编程一般都是同步编程,所谓同步编程的意思,和我们平时说的同时做几件事情完全不同. ...

  7. .NetCore 异步编程 - async/await

    前言: 这段时间开始用.netcore做公司项目,发现前辈搭的框架通篇运用了异步编程方式,也就是async/await方式,作为一个刚接触的小白,自然不太明白其中原理,最重要的是,这个玩意如果不明白基 ...

  8. .net 温故知新:【5】异步编程 async await

    1.异步编程 异步编程是一项关键技术,可以直接处理多个核心上的阻塞 I/O 和并发操作. 通过 C#.Visual Basic 和 F# 中易于使用的语言级异步编程模型,.NET 可为应用和服务提供使 ...

  9. .NET4.5 异步编程 async和await

    msdn介绍:https://msdn.microsoft.com/zh-cn/library/hh191443.aspx 其实很简单,标记了async的方法为异步方法,从方法的左大括号开始同步执行, ...

随机推荐

  1. Nested Loops join时显示no join predicate原因分析以及解决办法

    本文出处:http://www.cnblogs.com/wy123/p/6238844.html 最近遇到一个存储过程在某些特殊的情况下,效率极其低效, 至于底下到什么程度我现在都没有一个确切的数据, ...

  2. cesium核心类Viewer简介

    1.简单描述Viewer Viewer类是cesium的核心类,是地图可视化展示的主窗口,cesium程序应用的切入口,扮演必不可少的核心角色. 官网的英文解析如下: A base widget fo ...

  3. BPM的魅力何在?

    BPM(Business Process Management , 企业流程管理平台) 是带动企业流程自动化的帮 手,也是最能忠实反应出企业作业流程问题症结的系统工具,在管理上,BPM可以让管理者利用 ...

  4. Android开发学习—— Fragment

    #Fragment* 用途:在一个Activity里切换界面,切换界面时只切换Fragment里面的内容* 生命周期方法跟Activity一致,可以理解把其为就是一个Activity* 定义布局文件作 ...

  5. FineReport如何部署Tomcat服务器集群

    环境准备 Tomcat服务器集群中需要进行环境准备: Apache:Apache是http服务器,利用其对Tomcat进行负载均衡,这里使用的版本是Apache HTTP Server2.0.64: ...

  6. 借助 SIMD 数据布局模板和数据预处理提高 SIMD 在动画中的使用效率

    原文链接 简介 为发挥 SIMD1 的最大作用,除了对其进行矢量化处理2外,我们还需作出其他努力.可以尝试为循环添加 #pragma omp simd3,查看编译器是否成功进行矢量化,如果性能有所提升 ...

  7. Linux上课笔记--随手记Linux命令

    初次接触Linux就是感觉这系统不够友好不够人性化,因为首先接触电脑就是win,图形化界面什么操作都可以清晰看到.随着更多的接触越来越发现Linux的强大,虽然我只是一个小白,可我就是爱上他了.现在就 ...

  8. Ubuntu(Linux) + mono + jexus +asp.net MVC3 部署

    感谢  张善友 的建议,我把 微信订餐  由nginx 改成 jexus,目前运行状况来说,确实稳定了很多,再次感谢. 部署步骤参考 jexus官网:http://www.jexus.org/ htt ...

  9. Asp.Net跨平台:Ubuntu14.0+Mono+Jexus+Asp.Net

    Asp.Net跨平台的文章园子里有很多,这里给自己搭建的情况做一下总结,方便以后查看. 参考网站:   http://www.linuxdot.net/(Linux DotNET大本营 )  http ...

  10. AutoMapper(六)

    返回总目录 List和数组 AutoMapper只要求元素类型的配置而不要求可能会用到的任何数组或者list类型.比如,我们有一个简单的源和目标类型: public class Source{ pub ...