async/task/await三组合是.NET Framework 4.5带给.NET开发者的大礼,合理地使用它,可以提高应用程序的吞吐能力。

但是它的使用有点绕人,如果不正确使用,会带来意想不到的问题——比如await之后一直在等待,等到花儿也谢了,也等不来。

这篇博文将向你展示我们在实际开发中遇到的这个问题。

先看一段ASP.NET MVC示例代码:

public class BlogController : Controller
{
public async Task<ActionResult> AwaitDemo()
{
var responseHtml = GetResponseHtml("http://www.cnblogs.com/");
return Content(responseHtml);
} private string GetResponseHtml(string url)
{
return GetResponseContentAsync(url).Result;
} private async Task<string> GetResponseContentAsync(string url)
{
var httpClient = new System.Net.Http.HttpClient();
var response = await httpClient.GetAsync(url);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
return await response.Content.ReadAsStringAsync();
}
else
{
return "error";
}
}
}

代码说明:

  • 在上面的代码中,虽然在Action方法之前加了async Task<ActionResult>,但由于在方法体中没有使用await,所以实际还是以同步的方式执行的,与直接使用ActionResult是一样的。
  • GetResponseHtml是同步方法,GetResponseContentAsync是异步方法,在GetResponseHtml中调用了异步的GetResponseContentAsync。(如果调用的是第三方程序集,我们就不知道在GetResponseHtml中进行了异步调用,所以这个方法的设计是有问题的)

这段代码执行结果会是怎样呢?

——结果就是没有结果,一直在执行。。。

(注:如果在控制台应用程序中调用同样的GetResponseHtml,不会出现这个问题)

那如果解决这个问题呢:

解决方法一:在MVC Action中开启一个Task进行await

public async Task<ActionResult> AwaitDemo()
{
var responseHtml = await Task.Factory.StartNew(() =>
GetResponseHtml("http://www.cnblogs.com/"));
return Content(responseHtml);
}

解决方法二:将GetResponseHtml变成异步方法

public async Task<ActionResult> AwaitDemo()
{
var responseHtml = await GetResponseHtml("http://www.cnblogs.com/");
return Content(responseHtml);
} private async Task<string> GetResponseHtml(string url)
{
return await GetResponseContentAsync(url);
}

显然,第2个解决方法是更好的。

所以,我们在设计一个方法(method)时,如果调用了async方法,一定要将这个方法本身设计为async的。不然,别人调用时很容易踩着这个坑,然后就一直等啊等。。。等到花儿谢了,电脑冒烟了,也等不到。

编程就是Debug

或许是之前玩电脑太凶,所以就把电脑当作纯粹的娱乐工具。大学时坚决选了个和计算机靠不上边的专业:物理。为了向父母表示拳拳的向学之心,自己连电脑都没带,就屁颠屁颠的研究欧拉方程去了。

但门外汉最开始接触编程,还是来自本科的课程。本科时有五门和计算机相关的课程:

  • C语言。使用的是谭浩强的《C程序设计》。对教材不置可否,但这门课给我的印象是:程序员就是解决bug。再也不想转系到计算机学院了。
  • 算法与数据结构。当时的教材是高教版的《算法与数据结构》。书里的例子使用的是伪代码。现在觉得这不算差,但当时上机的时候总是一堆bug要改。对C语言不算熟练,所以很多bug不容易解决。
  • Fortran。教材是《FORTRAN语言》,谭浩强是作者之一。这是门古老的语言,但在科学运算方面运用很广,所以作为理科生必须要学习。和C语言给我的感觉类似,就是要不停的debug。痛苦极了。
  • 微机原理。教材是《微型计算机原理与接口技术》。主讲硬件原理和汇编语言。当时用UltraEdit加插件,来运行汇编语言。学习汇编时,也只是试着用了用加法、移动之类的语法,没有具体的项目。
  • 数据库。教材是本绿皮的,题目忘记了。还能记住的,就是不断分拆关系型数据库的表格,直到它满足某个范式。基本上没有太多实践。

回顾大学的这些课程,其实都算是计算机科学中相当重要的内容。问题是,这些课程都比较基础,偏理论,却轻实践。教材和老师的讲解也是如此,对于年轻人来说,乐趣少了些。具体的项目基本没有,自己很难看到效果。一时看不出这些课程的用途,就为了应付考试,将就的学吧。大好时光,还是挥洒在篮球场上吧。

大学期间还是出于兴趣,看了些Java和web的内容。Java看了《Core Java》的第一卷,但自己没有电脑,没法实践。还没把握到面向对象的精髓,就被轰然到来的期末备考裹挟走了。为了给女孩子惊喜,跟着w3cschool的教程,尝试做网站。学了html,css和php,但没钱租服务器,最后做了俩静态页面,差强人意。窘迫的年轻人。

创造才是乐趣

大学最后一年做毕业论文,阴差阳错,选了个三维重构流体运动的课题。这和计算机图形学沾上了边。当时用IDL来做图形处理和矩阵运算,可以很快看到算法对图形的处理效果。我一下子来了兴趣,连着两个假期都扑在这上面。空闲的时候,也是调程序、实验算法,看看结果如何。尽管导师评价代码太乱,不适合搞计算机,自己也是嘿嘿一笑,依然乐在其中。为了解决问题,自己还学了不少计算机图形学的内容,比如《图像处理、分析与机器视觉》。果然,兴趣是最大的学习动力。

在这期间,另一个重要的变化是接触Linux。为了做课题,我把自己的笔记本带到了学校。三年不见,这个本已经从曾经的“高富帅”变成了“矮挫熊”。听从朋友的建议,忍痛把操作系统换成了Ubuntu,以减少死机的次数。网上填个表,就有一张免费的cd寄到,顿时体验到开源的优越性。用了一段时间,总体感觉是,免费的果然差一些。比如Ubuntu上的办公软件就差office好多,更别说做的惨不忍睹的游戏了。唯一方便的是,学校里有一个Ubuntu镜像,所以可以以无比迅速的节奏来下载更新或者安装应用。真正享受Linux,还要等到未来。

需求的倒逼

本科毕业时,那所大学校园里快要溢出来的科研气氛给我打了鸡血。内心想的纯粹是搞科学研究。所以没怎么犹豫,就开始读博了。做的课题是流体计算相关的,因此需要在高性能电脑上并行运行。

高性能计算机的运行环境和普通电脑完全不同。首先,它安装的是CentOS,还没有任何的图形华界面,文本方面基本用vim。其次,由于要和别人竞争使用,要比较清楚的估计自己的工作量、所需的CPU数目和运行时间,还要查看空闲的资源,见缝插针。一个任务交上去,短的跑几天,长的跑几个星期。懒惰是创新的动力。为了不操那么多心,就写了些bash脚本来处理这些繁杂的事务,或者监视集群的运行状况。这才意识到bash和Linux工具(比如sed, awk, grep...)的好处。这期间读了《Linux Administration Handbook》,非常全面的一本Linux参考书,写的也很有趣。最后,高性能计算机是个并行的集群,需要了解并行算法和接口,所以读了《Parallel Programming with MPI》。

仅仅了解Linux的管理是不够的。在计算机上运行的是数值模型。这些数值模型是C语言和Fortran混合编写的。为了理解程序,认真读了《The C Programming Language》,《Expert C Programming》,《Fortran 90/95 for Scientists and Engineers》。这几本书的好处是简洁且重点清晰,读起来不费劲。然而,在集群上的编译连接很成问题。主流的编程可以依赖StackOverflow。但数值运算的很多问题太偏门,在网上找不到资料。一封询问邮件发出去,基本得不到什么有用的回应。几番折腾下来,心里发狠,还不如自己读源代码,自己解决问题。因此读了《Advanced Programming in the Unix Environment》(好一本厚书,读的过程不堪回首,读完真的学到很多)。这些基础知识帮助我解决了不少编译连接方面的问题。

数据处理是另一个问题。在工作最开始使用的是Matlab,但研究所里的许可证有限,有时要等到别人用完了才能去用。再加上Matlab的许多附加包价格不菲,也让我觉得不方便。有一次和教授聊起这个问题,教授说,那你可以试试Python。Python,以及Python下的Numpy和Scipy包可以满足我的需求。而且想想,Python是免费的,这无论对我,还是对未来可能雇佣我的研究机构来说,都可以省下笔钱。这么看,学Python是个蛮靠谱的事情。《Learning Python》是本很全面的Python教材。

写作的动力

出于分享Python心得的目的,也为了打发空闲的时间,开始在博客园写“Python快速教程”。写到标准库,发现Linux系统知识是必备的背景知识,所以重开了“Linux的概念与体系”系列。另一方面,在写网络相关的包时,发现自己对网络协议方面了解太少。《TCP/IP Illustrated》里有对网络协议非常全面的介绍。这里面学到的东西,也构成我的“协议森林”系列的文章基础。自己的文章得到认可,也更有动力去多看多学了。

在和其它博主交流时,感觉到自己在基础知识方面,还是有很大的差距。毕竟自己是个非计算机专业的“杂牌军”。一是对面向对象的本质了解不够,这在《Thinking in Java》里脑补了一下。二是算法和数据结构的知识太肤浅,因此基于《Data Structures and Algorithm Analysis in C》,自己实现了一系列的经典算法。三是没有设计数据库的实际经验,正在努力做一个项目,来获得实际经验。看看这三点,都是本科时候学残了的课。不是不报,时候未到啊。

门外汉的徘徊

从小屁孩时,拿着鼠标小心翼翼的点“开始”,自己还真的时徘徊了许久。幸运的是,人生几个转弯下来,我依然喜欢编程,喜欢静静的计算机打交道。有一件两件真心喜欢的事情,就是很大的幸福了。和许多专业的计算机人士相比,我依然是一个门外汉。这种门外汉的徘徊,其实感觉不坏。作为门外汉,没有要成为最好的负担,只用随心所欲的享受技术和写作。

作为门外汉,好的技术书和好的工具会有很大的影响。毕竟,门外汉说来就来,也说走就走,很容易一时的不享受而放弃。不能不说,是那些文辞优美又简洁的技术书,让我感受到编程的优美。而Ubuntu下方便免费的编程环境,铺平了自由尝试的道路。现在更方便的是,我们可以在互联网上找到各种各样的教程、资料和公开课。许多云平台工具也是免费的。所以,即时是门外汉,也可以很容易跨过那道大门。这是门外汉最好的时代了。

最后附一张图,开启我门外汉生活的电脑:

 
 
标签: ASP.NET MVCC#

async/task/await的更多相关文章

  1. c# async Task await Result 死锁

    最近项目数据量较大,使用 async Task异步增加执行效率 遇到问题,当前有2个计算非常耗时,现在需要你优化一下,这2个计算并行执行,2个计算执行完成后将2个结果sum返回给用户 当前我是这样实现 ...

  2. 异步方法的意义何在,Async和await以及Task的爱恨情仇,还有多线程那一家子。

    前两天刚感受了下泛型接口的in和out,昨天就开始感受神奇的异步方法Async/await,当然顺路也看了眼多线程那几个.其实多线程异步相关的类单个用法和理解都不算困难,但是异步方法Async/awa ...

  3. Await Async Task

    class Program { static void Main(string[] args) { Console.WriteLine("=======Start Main!======== ...

  4. The Task: Events, Asynchronous Calls, Async and Await

    The Task: Events, Asynchronous Calls, Async and Await Almost any software application today will lik ...

  5. 那些年我们一起追逐的多线程(Thread、ThreadPool、委托异步调用、Task/TaskFactory、Parallerl、async和await)

    一. 背景 在刚接触开发的头几年里,说实话,根本不考虑多线程的这个问题,貌似那时候脑子里也有没有多线程的这个概念,所有的业务都是一个线程来处理,不考虑性能问题,当然也没有考虑多线程操作一条记录存在的并 ...

  6. C# Task中的Func, Action, Async与Await的使用

    在说Asnc和Await之前,先说明一下Func和Action委托, Task任务的基础的用法 1. Func Func是一种委托,这是在3.5里面新增的,2.0里面我们使用委托是用Delegate, ...

  7. C# Thread、ThreadPool、Task、Invoke、BeginInvoke、async、await 汇总

    本文将主要通过"同步调用"."异步调用"."异步回调"三个示例来讲解在用委托执行同一个"加法类"的时候的的区别和利弊. ...

  8. C#.NET使用Task,await,async,异步执行控件耗时事件(event),不阻塞UI线程和不跨线程执行UI更新,以及其他方式比较

    使用Task,await,async,异步执行事件(event),不阻塞UI线程和不跨线程执行UI更新 使用Task,await,async 的异步模式 去执行事件(event) 解决不阻塞UI线程和 ...

  9. async和await用法(Task)

    原文:async和await用法 要理解async和await的用法,首先要了解Task相关知识,这里不做说明,因为这不是本文的重点. 如果你已经对Task很了解,那么如何使用async和await, ...

随机推荐

  1. 集成 Entity Framework

    ABP 基础设施层——集成 Entity Framework 本文翻译自ABP的官方教程<EntityFramework Integration>,地址为:http://aspnetboi ...

  2. 模拟linux下的ls -l命令

    #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h&g ...

  3. 图片 Base64码 转换

    import sun.misc.BASE64Decoder; private String getBase64Picture(String imgBase64Str) { FileOutputStre ...

  4. .NET缓存框架CacheManager---1、CacheManager的介绍

    在我们开发的很多分布式项目里面(如基于WCF服务.Web API服务方式),由于数据提供涉及到数据库的相关操作,如果客户端的并发数量超过一定的数量,那么数据库的请求处理则以爆发式增长,如果数据库服务器 ...

  5. Babelfish (STL)

    题目描述 You have just moved from Waterloo to a big city. The people here speak an incomprehensible dial ...

  6. hdu 2141 Can you find it?(二分查找变例)

    Problem Description Give you three sequences of numbers A, B, C, then we give you a number X. Now yo ...

  7. springmvc4

    web项目(使用html视图解析器)   完整配置springmvc4,最终视图选择的是html,非静态文件. 最近自己配置spring的时候,遇到很多问题,由于开发环境和版本的变化导致网友们给出的建 ...

  8. jquery 元素控制(附加元素/其他内容)引进和应用

    一个.在内部元素/外部附加元件 append,prepend:加入到该子元素  before,after:元素加入 html: <div id="content"> 在 ...

  9. 【翻译自mos文章】v$undostat视图没有依照每10分钟进行更新,v$undostat仅仅有1行(one rows)

    v$undostat视图没有依照每10分钟进行更新,v$undostat仅仅有1行(one rows) 參考原文: The V$UNDOSTAT view is not getting updated ...

  10. TFTP server组态

    TFTP server组态 2014-10-31北京海淀区  张俊浩 一.TFTP(Trivial File Transfer Protocol,简单文件传输协议或称小型文件传输协议) 是一种简化的文 ...