C#里的async和await

来源:互联网 发布:路基压实度灌砂法软件 编辑:程序博客网 时间:2024/05/18 02:06

C# vNext为了将异步变得更为简单,引入了2个关键字,asyncawait,下面简单介绍下这2个关键字给我们的编程带来怎么样的改变。

以一个标准的逻辑为例:下载一个远程URI,并将内容输出在界面上,假设我们已经有了显示内容的方法:

void Display(string text){// 不管是怎么实现的}

如果用标准的同步式写法,这代码相当之容易:

void ShowUriContent(string uri){using (WebClient client = new WebClient()){string text = client.DownloadString(uri);Display(text);}}


当然这不是我们讨论的重点,同步方式会造成线程的阻塞,必须选择WebClient下载完成才可以继续运行,如果这个过程在UI线程上执行,则会造成UI无响应的情况。同时网络是非常不可预测的外部条件,很可能因为网络状况不好导致程序长时间没有响应,显然不是我们希望得到的结果。

所以我们又有了异步的方案,.NET中最早的异常编程模式是Begin/End模式,不过WebClient作为WebRequest的高层封装,已经把这个模式给封装了:

void DownloadUri(string uri){using (WebClient client = new WebClient()){client.DownloadStringCompleted +=new DownloadStringCompletedEventHandler(ShowContent);client.DownloadStringAsync(uri);}} void ShowContent(object sender, DownloadStringCompletedEventArgs e){Display(e.Result);}


看看,好好的事情一变成异步,就变得麻烦无比。一个很明确逻辑的方法活生生拆成2个来处理,虽然可以用Lambda或者delegate来使代码上 进行简化,但依旧无可避免一段逻辑被拆成两段的痛苦。当更多的异步操作交叉在一起的时候,无论是代码的组织还是逻辑的梳理都会变得更加麻烦。

正因为如此,C# vNext引入了关键了,从语法上对此进行了改进,当使用asyncawait时,我们的代码会变成这样:

void async ShowUriContent(string uri){using (WebClient client = new WebClient()){string text = await client.DownloadStringTaskAsync(uri);Display(text);}}


悄悄地告诉你,我写上面这段代码的时候,是直接把同步方案的代码复制过来再稍微发了几个字符的……由此可见,在语言级别给予支持后,代码的编写将会是如何地顺畅和简便。这段代码看上去就是一段典型的同步逻辑,创建-下载-显示按部就班,唯一不同地就是在方法声明中加入了async关键字,在DownloadStringTaskAsync方法的调用时加入了await关键字。就这么神奇地,运行时变成了异步。ShowUriContent方法会在调用DownloadStringTaskAsync后退出,而下载过程会异步进行,当下载完成后,再进入Display方法的执行,期间不会阻塞线程,不会造成UI无响应的情况。


原创粉丝点击