async、await正确姿势
摘要
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 表达式,该表达式标记一个点,在该点上,直到等待的异步操作完成方法才能继续。 同时,将方法挂起,并且控件返回到方法的调用方。 本主题的下一节将解释悬挂点发生的情况。
在异步方法中,可使用提供的关键字和类型来指示需要完成的操作,且编译器会完成其余操作,其中包括持续跟踪控件以挂起方法返回等待点时发生的情况。 一些常规流程(例如,循环和异常处理)在传统异步代码中处理起来可能很困难。 在异步方法中,元素的编写频率与同步解决方案相同且此问题得到解决。
上面的方法执行过程

关系图中的数值对应于以下步骤。
事件处理程序调用并等待
AccessTheWebAsync异步方法。AccessTheWebAsync可创建 HttpClient 实例并调用 GetStringAsync 异步方法以下载网站内容作为字符串。GetStringAsync中发生了某种情况,该情况挂起了它的进程。 可能必须等待网站下载或一些其他阻止活动。 为避免阻止资源,GetStringAsync会将控制权出让给其调用方AccessTheWebAsync。GetStringAsync返回 Task<TResult>,其中TResult为字符串,并且AccessTheWebAsync将任务分配给getStringTask变量。 该任务表示调用GetStringAsync的正在进行的进程,其中承诺当工作完成时产生实际字符串值。由于尚未等待
getStringTask,因此,AccessTheWebAsync可以继续执行不依赖于GetStringAsync得出的最终结果的其他工作。 该任务由对同步方法DoIndependentWork的调用表示。DoIndependentWork是完成其工作并返回其调用方的同步方法。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正确姿势的更多相关文章
- 教你正确打开async/await关键字的使用
这段时间在项目开发中看到了一些async/await的使用,在aspnet core的host组件源码中也看到了许多的async/await代码.在开发时,正确的使用了async/await是可以提高 ...
- C#语法——泛型的多种应用 C#语法——await与async的正确打开方式 C#线程安全使用(五) C#语法——元组类型 好好耕耘 redis和memcached的区别
C#语法——泛型的多种应用 本篇文章主要介绍泛型的应用. 泛型是.NET Framework 2.0 版类库就已经提供的语法,主要用于提高代码的可重用性.类型安全性和效率. 泛型的定义 下面定义了 ...
- async...await在tcp通讯中的正确用法
引言 编程能力在不断的总结中进步以及成长,最近的半年里,对之前的开源项目代码进行回归,在重构的过程中进行了很多思考,很多次都想放弃重构,毕竟一个已经在使用的项目,重构基础代码就相当于重新开发了,不过最 ...
- Taro 多端开发的正确姿势:打造三端统一的网易严选(小程序、H5、React Native)
笔者所在的趣店 FED 早在去年 10 月份就已全面使用 Taro 框架开发小程序(当时版本为 1.1.0-beta.4),至今也上线了 2 个微信小程序.2 个支付宝小程序. 之所以选用 Taro, ...
- 深入理解理解 JavaScript 的 async/await
原文地址:https://segmentfault.com/a/1190000007535316,首先感谢原文作者对该知识的总结与分享.本文是在自己理解的基础上略作修改所写,主要为了加深对该知识点的理 ...
- .NET Core技术研究-HttpContext访问的正确姿势
将ASP.NET升级到ASP.NET Core之后,相信大家都会遇到HttpContext.Current无法使用的问题.这也是我们迁移ASP.NET Core必须解决的问题. 本文我们详细讨论一下, ...
- Flutter Webview添加Cookie的正确姿势
场景 h5页面要从cookie里面取数据,所以需要在flutter webview的cookie里面塞一些数据,设置的数据多达十几条:按照网上查的使用方式来设置,通过fiddler抓包发现,只能生效一 ...
- [.NET] 怎样使用 async & await 一步步将同步代码转换为异步编程
怎样使用 async & await 一步步将同步代码转换为异步编程 [博主]反骨仔 [出处]http://www.cnblogs.com/liqingwen/p/6079707.html ...
- 你眼中的async/await是什么样的?
又到了周末的code review环节,这次code review发现了一个对async/await的理解问题.让我们直奔主题: var foodsSearch = new FoodSearchSer ...
随机推荐
- 输出的数据格式是如何决定的-------Asp.net WebAPI学习笔记(二)
在上一篇文章<路由其实也可以很简单>,我们解决了路由问题,这篇文章,我们来研究剩下的另一个问题,为何我们的方法返回的是一个列表,输出到客户端的时候,变成json呢,大家应该还记得我们上一篇 ...
- 1月第2周业务风控关注|“扫黄打非”部门查处互动作业、纳米盒等20多个学习类App
易盾业务风控周报每周呈报值得关注的安全技术和事件,包括但不限于内容安全.移动安全.业务安全和网络安全,帮助企业提高警惕,规避这些似小实大.影响业务健康发展的安全风险. 1.全国"扫黄打非&q ...
- GitLab问题小结
1.内存消耗太大 (1)公司使用gitlab后,发现服务器内存居高不下,使用top命令查看内存消耗,发现服务器上git将近消耗一半内存资源.而且很奇怪的是竟然开启了32个进程.后经查资料,原来这跟gi ...
- raspberry pi wifi
vim /etc/network/interfaces 修改 wpa-ssid 和 wpa-psk
- python爬虫实践教学
i春秋作家:Mochazz 一.前言 这篇文章之前是给新人培训时用的,大家觉的挺好理解的,所以就分享出来,与大家一起学习.如果你学过一些python,想用它做些什么又没有方向,不妨试试完成下面几个案例 ...
- window.location API
概述 今天被自己鄙视了,竟然不会用window.location.search进行页面传值.现在好好总结下window.location API,记录一下供以后开发时参考,相信对其它人也有用. 页面传 ...
- java后端树形菜单使用递归方法
数据库的设计 使用ssm 实体类 mapper映射文件查询出所有的菜单 使用递归方法
- D02-R语言基础学习
R语言基础学习——D02 20190423内容纲要: 1.前言 2.向量操作 (1)常规操作 (2)不定长向量计算 (3)序列 (4)向量的删除与保留 3.列表详解 (1)列表的索引 (2)列表得元素 ...
- vue路由router的三种传参方式
方法三: 传参页面传递参数方式: this.$router.push({ path: 'indexTwoDetails', query: { "id": id } }) 接受参数页 ...
- 【xsy2272】 与运算 状压dp
题目大意:给你一个长度为$n$的序列$a$,我们定义$f_i$表示序列$a$前i项一次进行按位与运算后的值. 我们认为一个序列的价值为$\sum_{i=1}^{n}f_i$,现在你要重新排列序列$a$ ...