`
devgis
  • 浏览: 140341 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

C#里的async和await

 
阅读更多

C#发展至今,已经从最初的1.0到了4.0版本,不如来回顾一下各个版本都带来了什么:

  1. 1.0版本 - 基本C#语法。
  2. 2.0版本 - 泛型的支持,CLR进行了升级,从根本上支持了运行时泛型。
  3. 3.0版本 - LINQ,添加了from/join等类SQL关键字,添加了扩展函数,添加了编译期动态类型var关键字。
  4. 4.0版本 - dynamic关键字,CLR进行升级,加入DLR,开始对动态进行友好的支持。同时加入动态参数、参数默认值、泛型协变等特性。

可以看到,C#从诞生至今,经历2次CLR的升级,以及1次语法层面的扩展,其作为一个语言已经非常便利、强大。但是随着时代的发展,C#依旧在不断前进,而下一代C# vNext又即将诞生。每一代的C#都会在小的语法调整之外,带来一个震撼性的特性。从2.0的泛型、3.0的查询到4.0的动态,每一个版本的C#都有着一个主导的思想,而其他细节的改进和调整则是围绕着这个最基本的思想给予支持。

在这样一路明确的有且只有一个主导思想的升级路线上,下一代的C# vNext的核心思想又是什么呢?纵观当下的软件工程界,最热门的话题莫过于并行计算,为此C#早在4.0版本中就已经引入了Parallel Linq扩展,简化并行的开发。但是这远远不够,即便Parallel Linq已经提供了极大的便利,但其执行-回调模型依旧打破了编码人员以往对代码就是一行一行顺序执行的习惯思维。因此,C# vNext的主导思想是在这之上再给予更多的进化,即C# vNext将着眼于:

异步

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无响应的情况。

虽然高手们总是说不要关心语言,不要在意语言,真正重要的是思想。但是看着这样的代码,真的还能认为语言的优秀与否对生产效率没有影响吗?

至于如何实现这个效果,本篇并不想做太多的说明,因为本文的目的仅仅是向大家介绍一下下一代C#的一个特性。实现机制方面,相信大家都想得到,编译器会将方法体在await关键字前后打断,编译为Begin/End模式的异步模型。这并不是什么难事,但是能想到并付诸于实施却并不容易。至少JAVA7虽然强化了异步编程,但却没有让语言达到这样的程度。请不要不屑于语法糖,正如高手们所说,无论什么语言都不见得能改变设计的代价,那么实现过程的效率,就决定了项目本身的生产效率。

说回来,这个思想和老赵的[Jscex](http://blog.zhaojie.me/tag/Jscex/ 老赵点滴 - 追求编程之美)非常类似,都是试图通过一步编译,将异步的编程模型统一为同步模型,简化开发复杂度,提升生产效率。时至如今,还想说中国的程序员搞不出创造性的东西吗?

PS1:怎么去体验下C# vNext。

  1. 装备好Visual Studio 2010 + SP1,无论什么版本。
  2. Visual Studio Async CTP下载下来,并安装。
  3. 建个项目,现在你已经可以使用asyncawait关键字了,而诸如WebClient下的DownloadStringTaskAsync方法,则是在%MyDocument%\Microsoft Visual Studio Async CTP\Samples\AsyncCtpLibrary.dll下定义的扩展方法。

关于具体的实践和原理,可以看一看[C# 5.0 vNext - New Asynchronous Pattern](http://www.codeproject.com/KB/cs/async.aspx CodeProject)一文。

分享到:
评论

相关推荐

    浅谈C#中的Async和Await的用法详解

    众所周知C#提供Async和Await关键字来实现异步编程。在本文中,我们将共同探讨并介绍什么是Async 和 Await,以及如何在C#中使用Async 和 Await。 同样本文的内容也大多是翻译的,只不过加上了自己的理解进行了相关...

    C#_5.0新特性:Async和Await使异步编程更简单.pdf

    C#5.0引入的async和await关键字为C#语言的异步编程带来了革新。在此之前,异步编程常被认为是一个复杂和容易出错的过程,程序员不得不手动编写大量的代码来管理状态机、回调以及相关的线程同步问题。这不仅使得代码...

    说说C#的async和await的具体用法

    C# async 和 await 的具体用法 C# 5.0 中引入了 async 和 await 两个关键字,这两个关键字可以让开发者更方便地编写异步代码。async 和 await 的出现使得异步编程变得更加简单易懂。 async 关键字 async 关键字...

    C#关键字async/await用法

    "C#关键字async/await用法" ...async/await关键字是C#中的一种非常有用的语言特性,它可以使得异步编程变得更加简单和易于理解。但是,需要注意使用async/await关键字时的注意事项,以避免死锁的情况。

    async和await使用简单实例

    在C#编程中,`async`和`await`是用于异步编程的关键字,它们极大地简化了编写非阻塞代码的过程。异步编程是解决I/O密集型操作(如网络请求、读写文件等)时避免阻塞主线程的重要方法。下面我们将详细探讨这两个...

    使用Async和Await进行异步编程

    `async`和`await`关键字是C#语言为实现异步编程提供的核心工具,它们在Visual Studio 2015及更高版本中得到了广泛支持。 首先,我们来详细了解一下`async`关键字。`async`修饰符用于定义一个异步方法,这个方法会...

    C#异步编程async和await关键字及示例代码

    用用async关键字将方法标为异步方法,用await关键字等待异步任务的结果。出现了 await,指的是等待异步任务的结果。该示例代码,在主程序中用await关键字等待异步方法 myAsyncReadfile的结果。执行并需要在d盘根目录...

    async await 异常处理示例代码

    综上所述,理解和正确处理`async/await`中的异常至关重要。在编写异步代码时,应尽量避免`async void`,确保总是能够捕获和处理可能出现的异常。此外,使用`try-catch`块来封装`await`操作可以提供更清晰的错误处理...

    c# Async Await的介绍

    ### C#中的Async和Await详解 #### 一、引言 在C#中,`async`和`await`是用于简化异步编程的关键字。它们的引入极大地改善了开发人员编写高效、响应式应用程序的方式。本文旨在深入探讨`async`和`await`的基本原理...

    silverlight学习之路(2)异步编程趋于同步 利用async和await调用wcf服务

    在.NET框架中,`async`和`await`是两个关键的C#语言特性,它们简化了异步编程的实现。`async`关键字用于标记一个方法,表示该方法包含异步操作。而`await`关键字用于在异步方法中等待一个任务完成,但不会阻塞当前...

    C#基础系列:异步编程初探async和await

    确实,没有异步的多线程是单调的、乏味的,async和await是出现在C#5.0之后,它的出现给了异步并行变成带来了很大的方便。异步编程涉及到的东西还是比较多,本篇还是先介绍下async和await的原理及简单实现。  了解...

    详解C#中的Async和Await用法

    在C#编程中,`async`和`await`是用于实现异步编程的关键特性,它们在C# 5.0及以后的版本中引入,伴随着.NET Framework 4.5和Visual Studio 2012。异步编程允许程序在等待耗时操作(如网络I/O或数据库查询)时,不...

    C# async await使用方法

    在C#编程中,`async`和`await`是异步编程的关键关键字,它们使得开发者能够编写出非阻塞式的代码,从而提高了应用程序的性能和响应性。`async`和`await`通常与任务并行库(TPL)一起使用,为处理耗时的操作如I/O操作...

    后台耗时程序处理 async_await 异步程序

    总之,通过`async_await`和适当的后台处理机制,我们可以编写出既高效又响应的后台耗时任务处理程序,避免主线程阻塞,提升应用的整体性能和用户体验。在实际开发中,这种技术对于构建现代桌面应用、Web应用和移动...

    浅谈Async和Await如何简化异步编程(几个实例让你彻底明白)

    为了解决这个问题,C#引入了异步编程模型,特别是`async`和`await`关键字。`async`修饰符用于标记一个方法为异步方法,而`await`用于等待异步操作的结果,但不会阻塞当前线程。在`async`方法中,一旦遇到`await`,...

    韦_恩带你用好async/await异步多线程(C#5.0引入的特性)源码

    韦_恩带你用好async/await异步多线程(C#5.0引入的特性)源码: 博文请参考地址: https://blog.csdn.net/qq_42539194/article/details/124025155?spm=1001.2014.3001.5501 网盘地址:...

    【ASP.NET编程知识】ASP.Net中的async+await异步编程的实现.docx

    在 .NET Framework 4.5 框架和 C# 5.0 语法中,引入了一种新的基于任务的异步编程模型(TAP),通过 async 和 await 两个关键字,可以编写异步代码,极大简化了异步编程模型。 async 用来标记一个方法为异步方法,...

Global site tag (gtag.js) - Google Analytics