摘要

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

一个例子

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

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

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

再看下面的一个例子

原文:https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/concepts/async/index

// 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.)
// Here, it is Task<int> because the return statement returns an integer.
// - The method name ends in "Async."
async Task<int> AccessTheWebAsync()
{
// You need to add a reference to System.Net.Http to declare client.
HttpClient client = new HttpClient(); // GetStringAsync returns a Task<string>. That means that when you await the
// task you'll get a string (urlContents).
Task<string> 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 类型的返回语句,则为 Task<TResult>

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

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

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

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

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

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

上面的方法执行过程

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

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

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

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

    GetStringAsync 返回 Task<TResult>,其中 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; //结束

参考文章

https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/concepts/async/index 这篇文章对async、await介绍的非常详细,不懂的可以参考这个。

async、await正确姿势的更多相关文章

  1. 教你正确打开async/await关键字的使用

    这段时间在项目开发中看到了一些async/await的使用,在aspnet core的host组件源码中也看到了许多的async/await代码.在开发时,正确的使用了async/await是可以提高 ...

  2. C#语法——泛型的多种应用 C#语法——await与async的正确打开方式 C#线程安全使用(五) C#语法——元组类型 好好耕耘 redis和memcached的区别

    C#语法——泛型的多种应用   本篇文章主要介绍泛型的应用. 泛型是.NET Framework 2.0 版类库就已经提供的语法,主要用于提高代码的可重用性.类型安全性和效率. 泛型的定义 下面定义了 ...

  3. async...await在tcp通讯中的正确用法

    引言 编程能力在不断的总结中进步以及成长,最近的半年里,对之前的开源项目代码进行回归,在重构的过程中进行了很多思考,很多次都想放弃重构,毕竟一个已经在使用的项目,重构基础代码就相当于重新开发了,不过最 ...

  4. Taro 多端开发的正确姿势:打造三端统一的网易严选(小程序、H5、React Native)

    笔者所在的趣店 FED 早在去年 10 月份就已全面使用 Taro 框架开发小程序(当时版本为 1.1.0-beta.4),至今也上线了 2 个微信小程序.2 个支付宝小程序. 之所以选用 Taro, ...

  5. 深入理解理解 JavaScript 的 async/await

    原文地址:https://segmentfault.com/a/1190000007535316,首先感谢原文作者对该知识的总结与分享.本文是在自己理解的基础上略作修改所写,主要为了加深对该知识点的理 ...

  6. .NET Core技术研究-HttpContext访问的正确姿势

    将ASP.NET升级到ASP.NET Core之后,相信大家都会遇到HttpContext.Current无法使用的问题.这也是我们迁移ASP.NET Core必须解决的问题. 本文我们详细讨论一下, ...

  7. Flutter Webview添加Cookie的正确姿势

    场景 h5页面要从cookie里面取数据,所以需要在flutter webview的cookie里面塞一些数据,设置的数据多达十几条:按照网上查的使用方式来设置,通过fiddler抓包发现,只能生效一 ...

  8. [.NET] 怎样使用 async & await 一步步将同步代码转换为异步编程

    怎样使用 async & await 一步步将同步代码转换为异步编程 [博主]反骨仔 [出处]http://www.cnblogs.com/liqingwen/p/6079707.html  ...

  9. 你眼中的async/await是什么样的?

    又到了周末的code review环节,这次code review发现了一个对async/await的理解问题.让我们直奔主题: var foodsSearch = new FoodSearchSer ...

随机推荐

  1. Python基础语法-内置数据结构之列表

    列表的一些特点: 列表是最常用的线性数据结构 list是一系列元素的有序组合 list是可变的 列表的操作, 增:append.extend.insert 删:clear.pop.remove 改:r ...

  2. strom ui Topology 可视化视图各个指标含义说明

    In the visualization, spout components are represented as blue, while bolts are colored between gree ...

  3. UWP 大爆炸你个锤子

    今天看到  叫我蓝火火 s的 UWP中实现大爆炸效果(一) ,我也来说一下我的app [小薇自然语言处理]实现的大爆炸技术. 看一下效果先. 我的控件是基于wrappanel的,正如蓝火火说的,这样看 ...

  4. nginx-2.nginx是什么

    Nginx是一款自由的.开源的.高性能的HTTP服务器和反向代理服务器:同时也是一个IMAP.POP3.SMTP代理服务器: Nginx可以作为一个HTTP服务器进行网站的发布处理,另外Nginx可以 ...

  5. CE+X64dbg外挂制作教程 [提高篇]

    人造指针&基址 实验目标:通过向游戏注入一段特殊汇编代码,实现自动获取动态地址.省略找基址的麻烦 为什么会出现人造指针 ? 1.基址偏移层数太多,很难找 2.有些游戏根本找不到基址 人造指针有 ...

  6. spring cloud学习(二) 调用服务

    spring-cloud调用服务有两种方式,一种是Ribbon+RestTemplate, 另外一种是Feign. Ribbon是一个基于HTTP和TCP客户端的负载均衡器,其实feign也使用了ri ...

  7. CentOS的ssh sftp配置及权限设置[转载-验证可用]

    从技术角度来分析,几个要求:1.从安全方面看,sftp会更安全一点2.线上服务器提供在线服务,对用户需要控制,只能让用户在自己的home目录下活动3.用户只能使用sftp,不能ssh到机器进行操作 提 ...

  8. Liferay7 BPM门户开发之2: BPMN 2.0 规范入门 (Activiti BPMN extensions)

    Liferay最大的问题是BPM弱,如果做企业开发,BPM必不可少,所以直入主题,做个BPMN2入门. 本文参考地址:http://activiti.org/userguide/index.html# ...

  9. job任务执行流程与分区机制

    job任务执行流程    1.run job阶段        ①收集整个job的环境信息(比如通过conf设定的参数,还有mapperClass,reducerClass,以及输出kv类型)     ...

  10. oracle expdp impdp 导入导出备份

    数据库导入导出: 使用EXPDP和IMPDP时应该注意的事项: EXP和IMP是客户端工具程序,它们既可以在客户端使用,也可以在服务端使用. EXPDP和IMPDP是服务端的工具程序,他们只能在ORA ...