利用 async amp; await 的异步编程

一、异步编程的简介

  通过使用异步编程,你可以避免性能瓶颈并增强应用程序的总体响应能力。

  Visual Studio 2012 引入了一个简化的方法,异步编程,在 .NET Framework 4.5 和 Windows 运行时利用异步支持。编译器可执行开发人员曾进行的高难度工作,且应用程序保留了一个类似于同步代码的逻辑结构。因此,您仅需要进行一小部分工作就可以获得异步编程的所有优点。

 

二、异步提高响应能力

  异步对可能引起阻塞的活动(例如应用程序访问 Web 时)至关重要。对 Web 资源的访问有时很慢或会延迟。如果此类活动在同步过程中受阻,则整个应用程序必须等待。 在异步过程中,应用程序可继续执行不依赖 Web 资源的其他工作,直至潜在阻塞的任务完成。

  下图显示了异步编程提高响应能力的典型应用场景。包含从 .NET Framework 4.5 和 Windows 运行时中列出的一些包含支持异步编程的方法的类。

  

  由于所有与用户界面相关的活动通常共享一个线程,因此,异步对访问 UI 线程的应用程序来说尤为重要。 如果在一个同步应用程序中有任何的线程被阻塞了,那么所有线程都将被阻塞,再严重一点,你的应用程序将会停止响应。

  使用异步方法时,应用程序将继续响应 UI。例如,你可以调整窗口的大小或最小化窗口;如果你不希望等待应用程序结束,则可以将其关闭。

 

三、更容易编写的异步方法

  C# 中的 async 和 await 关键字都是异步编程的核心通过使用这两个关键字,你可以使用 .NET framework 或 Windows 运行时中的资源轻松创建异步方法(几乎与创建同步方法一样轻松)。

  下面的示例演示了一种使用 async 和 await 定义的异步方法。

/// <summary>

        /// 异步访问 Web 

        /// </summary>

        /// <returns></returns>

        /// <remarks>

        /// 方法签名的 3 要素:

        ///     ① async 修饰符

        ///     ② 返回类型 Task 或 Task<TResult>:这里的 Task<int> 表示 return 语句返回 int 类型

        ///     ③ 方法名以 Async 结尾

        /// </remarks>

        async Task<int> AccessTheWebAsync()

        {

            //记得 using System.Net.Http 哦

            var client = new HttpClient();


            //执行异步方法 GetStringAsync

            Task<string> getStringTask = client.GetStringAsync("http://www.google.com.hk/");


            //假设在这里执行一些非异步的操作

            DoIndependentWork();


            //等待操作挂起方法 AccessTheWebAsync

            //直到 getStringTask 完成,AccessTheWebAsync 方法才会继续执行

            //同时,控制将返回到 AccessTheWebAsync 方法的调用方

            //直到 getStringTask 完成后,将在这里恢复控制。

            //然后从 getStringTask 拿到字符串结果

            string urlContents = await getStringTask;


            //返回字符串的长度(int 类型)

            return urlContents.Length;

        }

  如果 AccessTheWebAsync 在调用 GetStringAsync 时没有其它操作,你可以用这样的方式来简化代码。

string urlContents = await client.GetStringAsync("http://www.google.com.hk/");

  

  根据以上代码进行简单总结:

  (1)方法签名包含一个 async 修饰符。

  (2)按照约定,异步方法的名称以“Async”后缀为结尾。

  (3)返回类型为下列类型之一:

    ① 如果你的方法有操作数为 TResult 类型的返回语句,则为 Task<TResult>。

    ② 如果你的方法没有返回语句或具有没有操作数的返回语句,则为 Task。

    ③ 如果你编写的是异步事件处理程序,则为 void。

  (4)方法通常包含至少一个 await 表达式,该表达式标记一个点,在该点上,直到等待的异步操作完成方法才能继续。 同时,将方法挂起,并且控制权将返回到方法的调用方。

  在异步方法中,可使用提供的关键字和类型来指示需要完成的操作,且编译器会完成其余操作。 

 

四、异步方法的控制流(核心)

  异步编程中最需弄清的是控制流,即如何从一个方法移动到另一个方法, 请用一颗感恩的心来观察下图。


  步骤解析:

  ① 事件处理程序调用并等待 AccessTheWebAsync 异步方法。

  ② AccessTheWebAsync 创建 HttpClient 对象并调用它的 GetStringAsync 异步方法来下载网站内容。

  ③ 假设 GetStringAsync 中发生了某种情况,该情况挂起了它的进程。可能必须等待网站下载或一些其他阻塞的活动。为避免阻塞资源,GetStringAsync 会将控制权出让给其调用方 AccessTheWebAsync。GetStringAsync 返回 Task,其中 TResult 为字符串,并且 AccessTheWebAsync 将任务分配给 getStringTask 变量。该任务表示调用 GetStringAsync 的正在进行的进程,其中承诺当工作完成时产生实际字符串值。

  ④ 由于尚未等待 getStringTask,因此,AccessTheWebAsync 可以继续执行不依赖于 GetStringAsync 得出最终结果的其他任务。该任务由对同步方法 DoIndependentWork 的调用表示。

  ⑤ DoIndependentWork 是完成其工作并返回其调用方的同步方法。

  ⑥ AccessTheWebAsync 已完成工作,可以不受 getStringTask 的结果影响。 接下来,AccessTheWebAsync 需要计算并返回该下载字符串的长度,但该方法仅在具有字符串时才能计算该值。因此,AccessTheWebAsync 使用一个 await 运算符来挂起其进度,并把控制权交给调用 AccessTheWebAsync 的方法。AccessTheWebAsync 将 Task<int> 返回至调用方。 该任务表示对产生下载字符串长度的整数结果的一个承诺。

  【备注】如果 GetStringAsync(即 getStringTask)在 AccessTheWebAsync 等待前完成,则控制权会保留在 AccessTheWebAsync 中。 如果异步调用过程 (getStringTask) 已完成,并且 AccessTheWebSync 不必等待最终结果,则挂起然后返回到 AccessTheWebAsync,但这会造成成本的浪费。

  在调用方内部(假设这是一个事件处理程序),处理模式将继续。在等待结果前,调用方可以开展不依赖于 AccessTheWebAsync 结果的其他工作,否则就需等待片刻。事件处理程序等待 AccessTheWebAsync,而 AccessTheWebAsync 等待 GetStringAsync。

  ⑦ GetStringAsync 完成并生成一个字符串结果。 字符串结果不是通过你预期的方式调用 GetStringAsync 所返回的。(请记住,此方法已在步骤 3 中返回一个任务。)相反,字符串结果存储在表示完成方法 getStringTask 的任务中。 await 运算符从 getStringTask 中检索结果。赋值语句将检索到的结果赋给 urlContents。

  ⑧ 当 AccessTheWebAsync 具有字符串结果时,该方法可以计算字符串长度。然后,AccessTheWebAsync 工作也将完成,并且等待事件处理程序可继续使用。 

 

  你可以尝试思考一下同步行为和异步行为之间的差异。当其工作完成时(第 5 步)会返回一个同步方法,但当其工作挂起时(第 3 步和第 6 步),异步方法会返回一个任务值。在异步方法最终完成其工作时,任务会标记为已完成,而结果(如果有)将存储在任务中。

 

五、线程

  异步方法旨在成为非阻塞操作异步方法中的 await 表达式在等待的任务正在运行时不会阻塞当前线程。相反,表达式在继续时注册方法的其余部分并将控制权返回到异步方法的调用方。

  async 和 await 关键字不会导致创建其他线程因为异步方法不会在其自身线程上运行,因此它不需要多线程。只有当方法处于活动状态时,该方法将在当前同步上下文中运行并使用线程上的时间。可以使用 Task.Run 将占用大量 CPU 的工作移到后台线程,但是后台线程不会帮助正在等待结果的进程变为可用状态。

  对于异步编程而言,该基于异步的方法优于几乎每个用例中的现有方法。具体而言,此方法比 BackgroundWorker 更适用于 IO 绑定的操作,因为此代码更简单且无需防止抢先争用条件。结合 Task.Run 使用时,异步编程比 BackgroundWorker 更适用于 CPU 绑定的操作,因为异步编程将运行代码的协调细节与 Task.Run 传输至线程池的工作区分开来。

 

六、async 和 await

  如果通过使用 async 修饰符指定某种方法为异步方法,则会出现下面两种现象。

  • 标记的异步方法可以使用 await 来指定悬挂点。await 运算符通知编译器异步方法只有直到等待的异步过程完成才能继续通过该点。同时,控制权将返回至异步方法的调用方。

    await 表达式中异步方法的挂起不能使该方法退出,并且 finally 块不会运行。

  • 标记的异步方法本身可以通过调用它的方法等待。

  异步方法通常包含 await 运算符的一个或多个匹配项,但缺少 await 表达式不会导致编译器错误。如果异步方法未使用 await 运算符标记悬挂点,则该方法将作为同步方法执行,不管异步修饰符如何。编译器将为此类方法发布一个警告。

 

七、返回类型和参数信息

  在 .NET 中,异步方法通常返回 Task 或 Task<TResult>。在异步方法中,await 运算符应用于通过调用另一个异步方法返回的任务。

  如果方法包含 指定类型 TResult 的操作数的 return 语句,则将 Task<TResult> 指定为返回类型。

  如果方法不含任何 return 语句或包含不返回操作数的 return 语句,则将 Task 用作返回类型。

  下面的示例演示如何声明并调用可返回 Task 或 Task<TResult> 的方法。

static async Task<Guid> Method1Async()  //Task<Guid>

        {

            var result = Guid.NewGuid();


            await Task.Delay(1);


            //这里返回一个 Guid 的类型

            return result;

        }


        static async Task Method2Async()  //Task

        {

            //Do...


            await Task.Delay(1);


            //Do...


            //这里没有 return 语句

         }


//调用 Method1Async

            //方式一

            Task<Guid> t1 = Method1Async();

            Guid guid1 = t1.Result;


            //方式二

            Guid guid2 = await Method1Async();


            //调用 Method2Async

            //方式一

            Task t2 = Method2Async();

            await t2;


            //方式二

            await Method2Async();

  每个返回的任务表示正在进行的工作。任务可封装有关异步进程状态的信息,如果未成功,则最后会封装来自进程的最终结果或进程引发的异常。

  异步方法还可以是具有 void 返回类型。该返回类型主要用于定义需要 void 返回类型的事件处理程序。异步事件处理程序通常用作异步程序的起始点。

  无法等待具有 void 返回类型的异步方法,并且一个 void 返回值的调用方无法捕获该方法引发的任何异常。

  异步方法无法声明 C# 中的 ref 或 out 参数,但此方法可以调用具有此类参数的方法。

 

八、命名的约定

  根据约定,将“Async”追加到具有 async 修饰符的方法名称。

  如果某一约定中的事件、基类或接口协定建议其他名称,则可以忽略此约定。例如,你不应重命名常用事件处理程序,例如 btnOpen_Click。

相关文章: 

  • Async/Await 异步编程中的最佳做法

  • [C#]async和await刨根问底

  • 剖析异步编程语法糖: async和await

  • Async/Await 异步编程中的最佳做法

原文地址:http://www.cnblogs.com/liqingwen/p/5922573.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/327737.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

xml配置文件显示为文本文件问题

idea 新建的xml文件显示为文本问题 原因: 由于新建不带后缀名的文件的时候 idea会相对智能的让你选择 文件规则 解决: settings->File types 中找到对应的文件类型显示 ,把 你不小心添加的 正则 给去除就好了, 我这里的配置如下图 可以自己进行设置&#xff08;&…

.NET应用迁移到.NET Core--调查案例

上周已经发过三篇文章讲述做.NET 应用迁移到.NET Core的一般方法&#xff0c;具体内容请看&#xff1a; .NET应用迁移到.NET Core&#xff08;一&#xff09; .NET应用迁移到.NET Core&#xff08;二&#xff09;风险评估 .NET应用迁移到.NET Core&#xff08;三&#xff09;从…

Ajax前后端对接---Springmvc

Springmvc实现 实体类user Data AllArgsConstructor NoArgsConstructor public class User {private String name;private int age;private String sex;}我们来获取一个集合对象&#xff0c;展示到前端页面 RequestMapping("/a2") public List<User> ajax2(…

缓存在大型网站架构中的应用

缓存的基本知识 在整个计算机体系构造中&#xff08;无论是硬件层面还是软件层面&#xff09;&#xff0c;缓存都是无处不在的。 在计算机硬件构造中&#xff0c;由于两种介质的速度不匹配&#xff0c;高速介质在和低速介质交互时速度趋向低速方&#xff0c;这就导致了高速介质…

win10安装dockerx docker的常见命令 可以子腾讯云上做做练习

参考资料 https://www.jianshu.com/p/e8427d12b3e0 百度搜索 docker hub 可以查找 你需要的镜像 https://hub.docker.com/?utm_sourcegetting_started_guide&utm_mediumembedded_Windows&utm_campaignfind_whalesay https://blog.csdn.net/zzq060143/article/de…

Jexus 5.8.2 正式发布为Asp.Net Core进入生产环境提供平台支持

Jexus 是一款运行于 Linux 平台&#xff0c;以支持 ASP.NET、PHP 为特色的集高安全性和高性能为一体的 WEB 服务器和反向代理服务器。最新版 5.8.2 已经发布&#xff0c;有如下更新&#xff1a; 1&#xff0c;现在大部分网站已经部署HTTPS&#xff0c;大家对于安全越来越重视&…

php移动代码,移动专区周级收录如何提交 复制这段php代码即可

今天我们来讲解下“移动专区的周级提交”很多朋友都在使用移动专区(之前的熊掌号)进行提交&#xff0c;但是天级提交只给10个额度&#xff0c;需要我们不断提交10个才会有所增长&#xff0c;但是我们可以使用“周级提交”可以直接享受5万的数据提交&#xff0c;对于我们站点的收…

搭建高可用的rabbitmq集群 + Mirror Queue + 使用C#驱动连接

我们知道rabbitmq是一个专业的MQ产品&#xff0c;而且它也是一个严格遵守AMQP协议的玩意&#xff0c;但是要想骚&#xff0c;一定需要拿出高可用的东西出来&#xff0c;这不本篇就跟大家说 一下cluster的概念&#xff0c;rabbitmq是erlang写的一个成品&#xff0c;所以知道如何…

Mybatis+mysql动态分页查询数据案例——配置映射文件(HouseDaoMapper.xml)

<?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace"houseDao" ><result…

手机钉钉在进行视频会议时怎么录屏

https://www.iefans.net/info/v1037168.html 钉钉在进行视频会议时怎么录屏 编辑&#xff1a;秩名2020-03-24 10:14:52 钉钉 类型&#xff1a;效率办公 语言&#xff1a;简体中文 安卓下载 扫一扫下载游戏 钉钉是一款很好用的学习办公软件&#xff0c;它的工呢很多&#xf…

Vue3学习(后端开发)

目录 一、安装Node.js 二、创建Vue3工程 三、用VSCode打开 四、源代码目录src 五、入门案例——手写src 六、测试案例 七、ref和reactive的区别 一、安装Node.js 下载20.10.0 LTS版本 https://nodejs.org/en 使用node命令检验安装是否成功 node 二、创建Vue3工程 在…

微软Ignite大会约起来

今年的微软Ignite技术大会今天开始了&#xff0c;要好好学习哦&#xff0c;提供直播地址&#xff0c;通过阅读原文链接可以直达直播地址 http://soft.zdnet.com.cn/special/microsoft_ignite_2016。 大会亮点 创新 IT 技术飞速发展促发了更多行业创新&#xff0c;因此您和您的企…

aria2c rpc php,aria2c 的基本配置,附带傻瓜式源码

经常需要配置&#xff0c;但是 每次都需要查找配置项的意义&#xff0c;所以索性写在这里&#xff0c;以便有个记录&#xff0c;下次无需查找。aria2c -d/Users/blueboz/Downloads \-c \-D \-laria.log \-j5 -k1M \-x16 -s16 \--file-allocationnone \--enable-rpc \--load-coo…

最全Windows下搭建go语言开发环境以及开发IDE

https://www.cnblogs.com/ynhmonster/p/8335797.html GO语言开发环境的搭建---Windows环境下 1、Golang下载 我是通过Golang中国下载的&#xff0c;因为去官网下载十分慢&#xff0c;甚至没有进度条。 下载地址&#xff1a; https://www.golangtc.com/download 我选择的是go1…

外媒:微信小程序顺应“APP中启动APP”的行业潮流

BI中文站 11月30日报道 上周&#xff0c;中国网络巨头腾讯的高级副总裁张小龙对外披露了一些照片&#xff0c;显示聊天工具微信开始整合“小程序”。这一功能可以让微信的用户在无需下载软件的基础上&#xff0c;使用各种互联网应用服务&#xff0c;极大扩展微信的功能。 据外媒…

SpringMVC(笔记)

MVC简介 普通的web项目每次都要进行手动的把jar包导进去&#xff0c;否则会报500&#xff0c;class not found [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VstjHhuz-1609824493673)(C:\Users\王东梁\AppData\Roaming\Typora\typora-user-images…

php 去掉url中的index.php,php 去掉url中的index.php

php去掉url中的index.php的方法&#xff1a;首先打开相应的代码文件&#xff1b;然后将if代码块嵌套在server代码块中&#xff1b;最后重启nginx服务器即可。本文操作环境&#xff1a;nginx1.0.4系统、PHP7.1版&#xff0c;DELL G3电脑nginx服务器去掉url中的index.php将if代码…

在ASP.NET Core中使用百度在线编辑器UEditor

0x00 起因 最近需要一个在线编辑器&#xff0c;之前听人说过百度的UEditor不错&#xff0c;去官网下了一个。不过服务端只有ASP.NET版的&#xff0c;如果是为了能尽快使用&#xff0c;只要把ASP.NET版的服务端作为应用部署在IIS上就可以立即使用了。不过我的需求并不急&#xf…

如何用TypeScript开发微信小程序

微信小程序来了&#xff01;这个号称干掉传统app的玩意儿虽然目前处于内测阶段&#xff0c;不过目前在应用号的官方文档里已经放出了没有内测号也能使用的模拟器了。 工具和文档可以参考官方文档&#xff1a;https://mp.weixin.qq.com/debug/wxadoc/dev/?t1477926804193 Type…

八幅漫画理解使用JSON Web Token设计单点登录系统

上次在《JSON Web Token - 在Web应用间安全地传递信息》中我提到了JSON Web Token可以用来设计单点登录系统。我尝试用八幅漫画先让大家理解如何设计正常的用户认证系统&#xff0c;然后再延伸到单点登录系统。 如果还没有阅读《JSON Web Token - 在Web应用间安全地传递信息》&…