你的位置:首页 > ASP.net教程

[ASP.net教程]第一章 Async异步编程简介


写在前面

  在学异步,有位园友推荐了《async in C#5.0》,没找到中文版,恰巧也想提高下英文,用我拙劣的英文翻译一些重要的部分,纯属娱乐,简单分享,保持学习,谨记谦虚。

  如果你觉得这件事儿没意义翻译的又差,尽情的踩吧。如果你觉得值得鼓励,感谢留下你的赞,祝各位爱技术的园友在今后每一次应该猛烈突破的时候,不选择知难而退。在每一次应该独立思考的时候,不选择随波逐流,应该全力以赴的时候,不选择尽力而为,不辜负每一秒存在的意义。

   转载和爬虫请注明原文链接http://www.cnblogs.com/tdws/p/5617242.html,博客园 蜗牛 2016年6月26日。


目录

第01章 异步编程介绍

第02章 为什么使用异步编程

第03章 手动编写异步代码

第04章 编写异步方法

第05章 Await究竟做了什么

第06章 以Task为基础的异步模式

第07章 异步代码的一些工具

第08章 哪个线程在运行你的代码

第09章 异步编程中的异常

第10章 并行使用异步编程

第11章 单元测试你的异步代码

第12章 ASP.NET应用中的异步编程

第13章 WinRT应用中的异步编程

第14章 编译器在底层为你的异步做了什么

第15章 异步代码的性能


第1章 异步编程介绍
   让我们从C#5.0异步编程Async和他将对你意味着什么来开始介绍吧!
 
异步编程

   如果我们在一个耗时的操作中使用异步的代码,在其执行过程中,我们不需要无谓的等待。这种方式和在耗时操作的整个执行过程中的阻塞型代码是相对的。


我们所说的耗时操作包括:

·网络请求

·硬盘数据访问

·延迟一段时间的操作

  全部的区别在于正在运行代码的线程。在广泛应用的编程语言当中,你的代码运行在操作系统的线程中。如果在遇到耗时操作时,你的线程可以继续去做其他事情,这就是异步编程。如果你的线程除了等待什么也不做,那就是同步的或者说是阻塞型代码。

当然我们还有第三种方式去处理耗时操作—轮询。这是一种不断重复“询问”耗时操作是否完成的操作。尽管它在处理段时间操作上有自己的地位,但这通常不是一个好的解决方案。

 

  你也许在过去的工作中使用过异步编程。你可能开启一个新的线程或者使用线程池,这也是异步编程,因为你所工作的线程可以不被阻塞地去继续做其他事情。而你的console app,像Console.ReadLine(),这就是阻塞型,在web app中,如果也是这样的设计等待用户输入,将会是多么糟糕呀。

  异步编程中很常见的难点在于这个操作在什么时候结束,以便于执行下一步的某些操作。但是这在阻塞型代码中,很容易做到:你只需要在将接下来的代码写在耗时操作的下一行就好。如果不加以处理,这种方式在异步的世界中是怎样也行不通的。因为几乎可以确定的是,你下一行代码是在耗时操作完成之前就已经执行了。

  为了解决这个问题,我们发明了一些方式,为了在后台操作完成后去执行下一步操作:

·将下一步操作所需的代码插在耗时操作代码主体的后面

·注册一个当耗时操作结束时会触发的方法

·在完成后传递委托或者Lambad(回调)

  如果你下一个操作需要在特定的线程上执行(例如Winform和WPF的UI线程),你还需要在这个线程上安排队列排序,这是很复杂的。


 
异步代码有什么了不起的?

   异步编程释放了它开始的线程,这有许多原因确实不错。首先,线程占用并且占用很少的资源,通常只用一个线程就可以完成主要的工作,就像UI线程,但是如果你不尽快释放它,你的app就会出现未响应状态。我们将会讨论更多的原因在下一章。

   最重要的,也是最令我激动的一点是:异步编程让我们得以有机会去尽情享受计算机并行计算带来的好处。异步编程让我们以新的并且合理的方式构建应用程序,用更细粒度的并行和无需编写难以维护的复杂代码。第十章将会详细探讨此可能性。


 
什么是异步编程?

   在C#5.0当中,微软编译器团队为我们增加了一个强大的新功能。

   它以两个新型关键字出现:。

·async

·await

   它当然依赖于一些环境,要求你使用.NET FrameWork4.5,才能你的async代码有用。

Async是属于C#编译器的一个功能,不能被封装到一个类库,它对你的源代码进行改造,就像在早期C#版本对Lambda和迭代器所做的事情一样。

 

   通过免去早期C#版本异步编程所需的复杂模式和代码,这个新功能使异步变得非常简单。有了这个功能,我们可以合理地用异步编程的风格编写整个项目。

   异步编程一直在C#中是可行的的,它以前涉及编程者大量的手工工作,现在C#的async关键出现后,异步编程的使用变得非常容易。


 
异步编程Async做了什么?

   Async功能提供了一种让你表达在耗时操作后需要做什么事情(执行什么代码)的方式,并且它易读易懂,表现为异步编程。

   Async方法被编译器转化的像你平时所写的阻塞代码,这里有一段简单的下载网页的阻塞型代码:

private void DumpWebPage(string uri){WebClient webClient = new WebClient();string page = webClient.DownloadString(uri);Console.WriteLine(page);}

   这里还有一段使用Async实现相同功能的代码:

private asyncvoid DumpWebPageAsync(string uri){WebClient webClient = new WebClient();string page = awaitwebClient.DownloadStringTaskAsync(uri);Console.WriteLine(page);}

   两段代码在表面上看起来是非常相似的,但是在其外表下,有很大的不同。

   被标记为Async的方法,要求方法使用await关键字,为了遵循惯例,我们也再方法的后缀名加上了Async。

   有趣的地方是await关键字,当编译器遇到它时,他将方法分开(chop the method up),事实上它是很复杂的,所以现在我介绍一个我觉得更易于理解的简单情况的假结构。

1.await后所有的代码被分离到另一个方法。

2.我们使用一个新版本叫做DownloadStringTaskAsync的DownloadString方法,它做和原版相同的事情,但它是异步的。

3.这意味着我们可以给它新的第二种方法,即在它完成时它会调用。我们使用一些“魔法”来做这件事,稍后我会告诉你。

4.当下载结束,它将会把我们调用回来带着已经下载好的可以使用的string字符串,在这种情况下,写到控制台。

//这就是await分解的方法,上文所说的假的结构(译者博客园蜗牛注解)private void DumpWebPageAsync(string uri){WebClient webClient = new WebClient();webClient.DownloadStringTaskAsync(uri)<- magic(SecondHalf); //魔力的方法调回来}private void SecondHalf(string awaitedResult){string page = awaitedResult;Console.WriteLine(page);}

   当它运行此代码时,调用线程会发生什么?当线程抵达DownloadStringTaskAsync方法,下载工作开始,但并不在此线程中执行,在这个线程上,我们抵达了方法的结尾或者说是return,这个线程下一步做什么由我们调用者来决定。如果是UI线程,它将会返回执行用户操作,除此外,它的资源将会被释放,这意味着我们在做异步编程!


 
异步编程并不能解决所有问题

    异步代码被微软编译器开发团队尽可能设计的像你常写的阻塞(同步)代码,我们可以把耗时操作或者远程操作处理地像本地操作和快速。但是保持和异步调用一样的性能和优势。

   然而,这样的设计不是让你忘记Async是后台操作还有发生回调。你需要小心很多事情,包括:

·异常和try-catch-finally模块

·方法的返回值

·线程和上下文

·性能

   如果不了解它真正发生了什么,你的应用程序可能会意想不到的挂掉,并且你将无法理解异常信息和没有能力去解决问题。

 

写在最后  

 终于翻译好了第一章,四页,花了几个小时。昨天读了一遍,没读懂,今天翻译一遍果然收获颇多。如果您表示支持,给个赞吧!