await/async闲说
自从C#5.0增加异步编程之后,异步编程越来越简单,async和await用的地方越来越多,越来越好用,只要用异步的地方都是一连串的异步,如果想要异步编程的时候,需要从底层开始编写,这样后边使用的时候就是异步,那么底层是如何实现??我们如何编写高效率的异步方法??
#了解基于任务的异步模式(TAP)
基于任务的异步编程模型 (TAP) 提供了异步代码的抽象化,你只需像往常一样将代码编写为一连串语句即可,在开始调用的地方运行。例如:var task = method()①; await task②; 在①的时候开始运行可能还没有运行完,在②程序挂起等待运行完,中间怎么运行的你不需要知道,编译器会做若干操作的。当开启多个任务的时候,像要他们都执行完,在执行其他的时候,可以await Task.WhenAll(task1,task2 .....);
#了解async/await
await 运算符应用于异步方法,在方法的执行中插入挂起点,直到所等待任务完成。使用async 和await定义异步方法不一定会创建新线程,当编译器看到await关键字时,线程会挂起等待运行结束。
await 仅可用于由 async 关键字修改的异步方法中,使用 async 修饰符定义的方法通常包含一个或多个 await 表达式,使用await运算符的任务通常是实现[基于任务的异步模式(TAP)]的方法调用返回,返回值包括 Task、Task<TResult>、ValueTask 和 ValueTask<TResult> 对象的方法。
# 调用 Task.Wait() 或者 Task.Result 立刻产生死锁的充分条件
1. 调用 Wait() 或 Result 的代码位于 UI 线程。
2. Task 的实际执行在其他线程,且需要返回 UI 线程。
死锁的原因:UWP、WPF、Windows Forms 程序的 UI 线程都是单线程的。为了避免产生死锁,你应该一条道走到黑, Async All the Way。或者.ConfigureAwait(false)
# ValueTask与Task的区别
7.0为async新增的ValueTask的作用(如果没有在Nuget上下载System.Threading.Tasks.Extensions,ValueTask就在这个库中),ValueTask用于值类型的异步;Task为引用类型的,每次需要分配空间。
例如:

public async Task<int> CalculateSum(int a, int b) {
if (a == 0 && b == 0)
{
return 0;
}
return await Task.Run(() => a + b);
}

当a,b=0的时候不会运行到task里,这个时候返回task就造成了资源的浪费,修改为以下会效率更高

public async ValueTask<int> CalculateSum2(int a, int b)
{
if (a == 0 && b == 0)
{
return 0;
} return await Task.Run(() => a + b);
}

但是也不是说到处用ValueTask会好,当是引用类型的时候,用ValueTask,你需要关注更多的数据,这个时候用Task会更好。
# await/async原理分析

[AsyncStateMachine(typeof(Class1.<CalculateSum2>d__1))]
public ValueTask<int> CalculateSum2(int a, int b)
{
Class1.<CalculateSum2>d__1 <CalculateSum2>d__;
<CalculateSum2>d__.a = a;
<CalculateSum2>d__.b = b;
<CalculateSum2>d__.<>t__builder = AsyncValueTaskMethodBuilder<int>.Create();
<CalculateSum2>d__.<>1__state = -1;
AsyncValueTaskMethodBuilder<int> <>t__builder = <CalculateSum2>d__.<>t__builder;
<>t__builder.Start<Class1.<CalculateSum2>d__1>(ref <CalculateSum2>d__);
return <CalculateSum2>d__.<>t__builder.Task;
}

对CalculateSum2代码解析,发现没有await/async,原来又是编译器提供的语法糖。

[__DynamicallyInvokable, DebuggerStepThrough, SecuritySafeCritical]
public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine
{
if (stateMachine == null)
{
throw new ArgumentNullException("stateMachine");
}
ExecutionContextSwitcher executionContextSwitcher = default(ExecutionContextSwitcher);
RuntimeHelpers.PrepareConstrainedRegions();
try
{
ExecutionContext.EstablishCopyOnWriteScope(ref executionContextSwitcher);
stateMachine.MoveNext();
}
finally
{
executionContextSwitcher.Undo();
}
}

对Start方法进行分析,可以看出MoveNext,程序的运行其实还是一步一步进行的,那么await/async会不会创建一个线程,这倒是不一定,这个由线程池决定,那么异步了不创建一个线程,怎么异步的,这里的异步可能是运行在已经有的线程上。
await/async闲说的更多相关文章
- C#中await/async闲说
自从C#5.0增加异步编程之后,异步编程越来越简单,async和await用的地方越来越多,越来越好用,只要用异步的地方都是一连串的异步,如果想要异步编程的时候,需要从底层开始编写,这样后边使用的时候 ...
- javascript异步编程的前世今生,从onclick到await/async
javascript与异步编程 为了避免资源管理等复杂性的问题, javascript被设计为单线程的语言,即使有了html5 worker,也不能直接访问dom. javascript 设计之初是为 ...
- Silverlight项目笔记1:UI控件与布局、MVVM、数据绑定、await/async、Linq查询、WCF RIA Services、序列化、委托与事件
最近从技术支持转到开发岗,做Silverlight部分的开发,用的Prism+MVVM,框架由同事搭好,目前做的主要是功能实现,用到了一些东西,侧重于如何使用,总结如下 1.UI控件与布局 常用的主要 ...
- 5分种让你了解javascript异步编程的前世今生,从onclick到await/async
javascript与异步编程 为了避免资源管理等复杂性的问题,javascript被设计为单线程的语言,即使有了html5 worker,也不能直接访问dom. javascript 设计之初是 ...
- es7 await/async解决异步问题
最近做项目遇到一个问题,前端调用ie浏览器中的ocx的方法去查询数据,查询完之后ocx给一个返回值,然后js将返回值当参数传入到另外的函数中去做数据处理,但是遇到一个问题是前端需要异步去执行这个过程 ...
- promise 的基本概念 和如何解决js中的异步编程问题 对 promis 的 then all ctch 的分析 和 await async 的理解
* promise承诺 * 解决js中异步编程的问题 * * 异步-同步 * 阻塞-无阻塞 * * 同步和异步的区别? 异步;同步 指的是被请求者 解析:被请求者(该事情的处理者)在处理完事情的时候的 ...
- 如何避免 await/async 地狱
原文地址:How to escape async/await hell 译文出自:夜色镇歌的个人博客 async/await 把我们从回调地狱中解救了出来,但是如果滥用就会掉进 async/await ...
- 【.NET异步编程系列1】:await&async语法糖让异步编程如鱼得水
前导 Asynchronous programming Model(APM)异步编程模型以BeginMethod(...) 和 EndMethod(...)结对出现. IAsyncResult Beg ...
- 使用Typescript写的Vue初学者Hello World实例(实现按需加载、跨域调试、await/async)
万事开头难,一个好的Hello World程序可以节省我们好多的学习时间,帮助我们快速入门.Hello World程序之所以是入门必读必会,就是因为其代码量少,简单易懂.但我觉得,还应该做到功能丰富, ...
随机推荐
- learning scala implicit class
隐式类可以用来扩展对象的功能非常方便 example: object ImplicitClass_Tutorial extends App { println("Step 1: How to ...
- [GXOI/GZOI2019]特技飞行
题目链接 [https://www.luogu.org/problem/P5302] 思路:这道题可以说是两道题的合并.注意到\(c\)的分数与 \(a\)和\(b\)的分数 无关,也就是说可以分成两 ...
- The 2019 ICPC China Nanchang National Invitational and International Silk-Road Programming Contest
目录 Contest Info Solutions A. Attack B. Polynomial E. Interesting Trip F. Sequence G. Winner H. Anoth ...
- The Preliminary Contest for ICPC China Nanchang National Invitational
目录 Contest Info Solutions A. PERFECT NUMBER PROBLEM D. Match Stick Game G. tsy's number H. Coloring ...
- linux系列(四):mkdir命令
1.命令格式: mkdir [选项] 目录名 2.命令功能: 通过 mkdir 命令可以实现在指定位置创建以 DirName(指定的文件名)命名的文件夹或目录.要创建文件夹或目录的用户必须对所创建的文 ...
- C++ 利用指针和数组以及指针和结构体实现一个函数返回多个值
C++ 利用指针和数组实现一个函数返回多个值demo1 #include <iostream> using namespace std; int* test(int,int,int); i ...
- 小程序开发--API之登录授权逻辑
小程序登录授权获取逻辑 原生的小程序提供许多开放接口供使用者开发,快速建立小程序内的用户体系. 下面将小程序校验.登录.授权.获取用户信息诸多接口串联起来,以便更直观的认识到这些接口是如何在实际应用中 ...
- EXTJS框架-入门实例
extjs框架是一个JavaScript框架,可以渲染出丰富的控件 实例: 代码: <html> <head> <title>test</title> ...
- Linux下MySQL的操作(最全)
注意:这里以mariadb为例 启动mysql服务 systemctl start mariadb 登录mysql mysql -u root -p SQL语言分类 - 数据定义语言:简称[DDL]( ...
- vmware如何克隆多个linux系统
安装一次系统相对来说耗时较长,且还要做各种配置,那么克隆就不失为一种好的选择.接下来我把我做系统克隆的步骤写下来,供大家参考: 右键点击已经安装的虚拟机,选择管理-->克隆,接下来弹出一个窗口 ...