博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
async、await正确姿势
阅读量:6579 次
发布时间:2019-06-24

本文共 3384 字,大约阅读时间需要 11 分钟。

摘要

async、await是在C# 5.0之后引入的一种简化异步操作的方式。使用它们之后,可以使我们的编写异步操作更加方便快捷,维护以及阅读起来更方便。

一个例子

async、await虽然简化了我们编写异步方法。但也很容易让人产生误解。首先看一个例子:

public static async Task
AddAsync(int x, int y) { return await Task.Factory.StartNew(() => { return x + y; }); }

这种加了async、await叫不叫异步呢?答案肯定不是的。我们可以这样叫这种方法:加了async、await标记的同步方法。

再看下面的一个例子

原文:  

// Three things to note in the signature:  //  - The method has an async modifier.   //  - The return type is Task or Task
. (See "Return Types" section.) // Here, it is Task
because the return statement returns an integer. // - The method name ends in "Async." async Task
AccessTheWebAsync() { // You need to add a reference to System.Net.Http to declare client. HttpClient client = new HttpClient(); // GetStringAsync returns a Task
. That means that when you await the // task you'll get a string (urlContents). Task
getStringTask = client.GetStringAsync("http://msdn.microsoft.com"); // You can do work here that doesn't rely on the string from GetStringAsync. DoIndependentWork(); // The await operator suspends AccessTheWebAsync. // - AccessTheWebAsync can't continue until getStringTask is complete. // - Meanwhile, control returns to the caller of AccessTheWebAsync. // - Control resumes here when getStringTask is complete. // - The await operator then retrieves the string result from getStringTask. string urlContents = await getStringTask; // The return statement specifies an integer result. // Any methods that are awaiting AccessTheWebAsync retrieve the length value. return urlContents.Length; }

上面的方法GetStringAsync,如果不需要返回值,可以移步进行执行,然后会执行方法DoIndependentWork方法,知道await  getStringTask拿到GetStringAsync方法的返回值。

以下特征总结了使上一个示例成为异步方法的原因。

  • 方法签名包含 async 修饰符。

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

  • 返回类型为下列类型之一:

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

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

    • Void:如果要编写异步事件处理程序。

    • 包含 GetAwaiter 方法的其他任何类型(自 C# 7 起)。

    有关详细信息,请参见本主题后面的“返回类型和参数”。

  • 方法通常包含至少一个 await 表达式,该表达式标记一个点,在该点上,直到等待的异步操作完成方法才能继续。 同时,将方法挂起,并且控件返回到方法的调用方。 本主题的下一节将解释悬挂点发生的情况。

在异步方法中,可使用提供的关键字和类型来指示需要完成的操作,且编译器会完成其余操作,其中包括持续跟踪控件以挂起方法返回等待点时发生的情况。 一些常规流程(例如,循环和异常处理)在传统异步代码中处理起来可能很困难。 在异步方法中,元素的编写频率与同步解决方案相同且此问题得到解决。

上面的方法执行过程

关系图中的数值对应于以下步骤。

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

  2. AccessTheWebAsync 可创建  实例并调用  异步方法以下载网站内容作为字符串。

  3. GetStringAsync 中发生了某种情况,该情况挂起了它的进程。 可能必须等待网站下载或一些其他阻止活动。 为避免阻止资源,GetStringAsync 会将控制权出让给其调用方 AccessTheWebAsync

    GetStringAsync 返回 ,其中 TResult 为字符串,并且 AccessTheWebAsync 将任务分配给 getStringTask 变量。 该任务表示调用 GetStringAsync 的正在进行的进程,其中承诺当工作完成时产生实际字符串值。

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

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

  6. AccessTheWebAsync 已用完工作,可以不受 getStringTask 的结果影响。 接下来,AccessTheWebAsync 需要计算并返回该下载字符串的长度,但该方法仅在具有字符串时才能计算该值。

    因此,AccessTheWebAsync 使用一个 await 运算符来挂起其进度,并把控制权交给调用 AccessTheWebAsync 的方法。 AccessTheWebAsync 将 Task<int> 返回给调用方。 该任务表示对产生下载字符串长度的整数结果的一个承诺。

 总结

简单一句话,并不是所有的加了async和await关键字的方法就是异步方法。可以这样理解 await 的位置决定了到底是不是异步方法,如果直接await xxxAsync那么是挂起当前方法直到拿到返回值才会执行下面的逻辑,这样就是一种同步方法了。异步是类似这样的 代码块:

task  t=xxAsync();//其它业务逻辑await t;//结束

参考文章

 这篇文章对async、await介绍的非常详细,不懂的可以参考这个。

转载于:https://www.cnblogs.com/wolf-sun/p/7552910.html

你可能感兴趣的文章
下拉菜单
查看>>
[清华集训2014]玛里苟斯
查看>>
【MVC+EasyUI实例】对数据网格的增删改查(上)
查看>>
Project Euler 345: Matrix Sum
查看>>
你可能不知道的技术细节:存储过程参数传递的影响
查看>>
[摘录]调动员工积极性的七个关键
查看>>
.htaccess 基础教程(四)Apache RewriteCond 规则参数
查看>>
Android控件之HorizontalScrollView 去掉滚动条
查看>>
UVM中的class--2
查看>>
ORACLE 存储过程异常捕获并抛出
查看>>
root用户重置其他密码
查看>>
Oracle推断值为非数字
查看>>
多年前写的一个ASP.NET网站管理系统,到现在有些公司在用
查看>>
vue-cli中理不清的assetsSubDirectory 和 assetsPublicPath
查看>>
从JDK源码角度看Short
查看>>
五年 Web 开发者 star 的 github 整理说明
查看>>
Docker 部署 SpringBoot 项目整合 Redis 镜像做访问计数Demo
查看>>
中台之上(五):业务架构和中台的难点,都是需要反复锤炼出标准模型
查看>>
使用模板将Web服务的结果转换为标记语言
查看>>
inno setup 打包脚本学习
查看>>