Async和Await异步编程的原理

本文深入探讨了.NET中Async和Await异步编程的实现原理,介绍了.NET提供新功能的三种方法,并详细讲解了Async和Await如何基于编译器转化为状态机进行工作,强调了它们并不会直接创建新线程,而是通过Task和状态机实现异步操作。同时,文章提供了创建真正异步函数的示例,展示了如何使用Task类实现异步功能。
摘要由CSDN通过智能技术生成
               

1. 简介 

 

从4.0版本开始.NET引入并行编程库,用户能够通过这个库快捷的开发并行计算和并行任务处理的程序。在4.5版本中.NET又引入了Async和Await两个新的关键字,在语言层面对并行编程给予进一步的支持,使得用户能以一种简洁直观的方式实现并行编程。因为在很多文档里针对Async和Await这两个关键字的使用都被称为异步编程,为了更符合大众的阅读习惯,我们使用异步编程这个叫法,意思上和并行编程完全一样。

 

关于Async和Await异步编程的功能说明和使用介绍,MSDN上有详细文档,链接如下:

 

http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx

 

其它地方也可以搜索到很多相关文章,这里就不再赘述,本文主要介绍的是异步编程是如何现实的,背后的原理是什么。

 

注意:在您阅读下面内容之前请确保已经熟悉了异步编程的基本方法。

 

2. .NET中提供新功能的几种方法

 

在.NET中,提供新功能有三种方法:基于运行时、基于编译器和基于类库。

 

2.1 基于运行时的实现

 

显而易见,.NET中大多数功能都是基于运行时实现的。比如的类定义的语法、方法的调用的语法以及所有基本编程语法都有对应的IL代码,这也正是定义运行时的内容之一。所以能编译为对应专有IL代码的功能必然是基于运行时实现的。

 

2.2 基于编译器

 

基于编译器的实现,最常见的例子就是上下文using和yield。上下文using在VB.NET里干脆就没有对应的语法,C#编译器替你做了你在老版本的C#中或VB.NET里要做的工作,就是写try、finally和Dispose语句。提供基于编译器的新功能微软不需要修改运行时。

 

2.3 基于类库

 

这个太直观了,直观到拿到这里说都显得多余,都不宜与前两种并列在一起。所有的编程语言都是通过库为开发者提供强大的开发功能的,库的丰富程度最终决定一个语言的发展前景。

 

.NET现在常用的运行时只有2.0和4.0两个版本,3.0 和3.5都是2.0的运行时;4.5的运行时是4.0,它是在编译器功能和类库上对4.0的扩展。

 

3. Async和Await的实现

 

讲到这里,您或许已经猜测到八九分了,这个await关键字的出现位置、使用方式以及运行逻辑和yield是如此的像,不错,await和async就是一种基于编译器的功能(C#和VB.NET都提供了这个功能),不仅如此,它在实现原理上也和yield非常像——那就是await/async和yield都是被编译器转化为了状态机。

 

状态机是一种非常常用的编程模式,基本上所有的编译器都是基于状态机实现的,当您看这篇博文的时候,浏览器就是使用状态机将从cnblog.com服务器上获取的html文本解析为html元素树,再绘制到屏幕上。

 

如何发现或者证实这一点呢,那就是用.NET的反编译器,每当出现新语法,好奇者都喜欢用反编译器看一下生成的IL代码究竟是什么样子。在Reflector被收购收费后(引来吐槽无数),作者一直使用JustDecompile(Telerik在Reflector收费后立即推出的免费程序),使用JustDecompile时,需要在该程序的Settings中将Show compiler generated types and members选中。也可以用.NET SDK自带的ILDASM来反编译,功能虽然最强大,但是只能反编译为IL汇编语言,显得有些不便。

 

下载MSDN上的示例Async Sample Example from Asynchronous Programming with Async and Await,这是一个简单的WPF应用,用于演示Async/Await异步编程,主要代码如下:

 
  
    public partial class MainWindow : Window    {        // Mark the event handler with async so you can use await in it.        private async void StartButton_Click(object sender, RoutedEventArgs e)        {            // Call and await separately.            //Task<int> getLengthTask = AccessTheWebAsync();            //// You can do independent work here.            //int contentLength = await getLengthTask;            int contentLength = await AccessTheWebAsync();            resultsTextBox.Text +=                String.Format("\r\nLength of the downloaded string: {0}.\r\n", contentLength);        }        // Three things to note in the signature:        //  - The method has an async modifier.         //  - The return type is Task or Task<T>. (See "Return Types" section.)        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值