自从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闲说的更多相关文章

  1. C#中await/async闲说

    自从C#5.0增加异步编程之后,异步编程越来越简单,async和await用的地方越来越多,越来越好用,只要用异步的地方都是一连串的异步,如果想要异步编程的时候,需要从底层开始编写,这样后边使用的时候 ...

  2. javascript异步编程的前世今生,从onclick到await/async

    javascript与异步编程 为了避免资源管理等复杂性的问题, javascript被设计为单线程的语言,即使有了html5 worker,也不能直接访问dom. javascript 设计之初是为 ...

  3. Silverlight项目笔记1:UI控件与布局、MVVM、数据绑定、await/async、Linq查询、WCF RIA Services、序列化、委托与事件

    最近从技术支持转到开发岗,做Silverlight部分的开发,用的Prism+MVVM,框架由同事搭好,目前做的主要是功能实现,用到了一些东西,侧重于如何使用,总结如下 1.UI控件与布局 常用的主要 ...

  4. 5分种让你了解javascript异步编程的前世今生,从onclick到await/async

      javascript与异步编程 为了避免资源管理等复杂性的问题,javascript被设计为单线程的语言,即使有了html5 worker,也不能直接访问dom. javascript 设计之初是 ...

  5. es7 await/async解决异步问题

    最近做项目遇到一个问题,前端调用ie浏览器中的ocx的方法去查询数据,查询完之后ocx给一个返回值,然后js将返回值当参数传入到另外的函数中去做数据处理,但是遇到一个问题是前端需要异步去执行这个过程 ...

  6. promise 的基本概念 和如何解决js中的异步编程问题 对 promis 的 then all ctch 的分析 和 await async 的理解

    * promise承诺 * 解决js中异步编程的问题 * * 异步-同步 * 阻塞-无阻塞 * * 同步和异步的区别? 异步;同步 指的是被请求者 解析:被请求者(该事情的处理者)在处理完事情的时候的 ...

  7. 如何避免 await/async 地狱

    原文地址:How to escape async/await hell 译文出自:夜色镇歌的个人博客 async/await 把我们从回调地狱中解救了出来,但是如果滥用就会掉进 async/await ...

  8. 【.NET异步编程系列1】:await&async语法糖让异步编程如鱼得水

    前导 Asynchronous programming Model(APM)异步编程模型以BeginMethod(...) 和 EndMethod(...)结对出现. IAsyncResult Beg ...

  9. 使用Typescript写的Vue初学者Hello World实例(实现按需加载、跨域调试、await/async)

    万事开头难,一个好的Hello World程序可以节省我们好多的学习时间,帮助我们快速入门.Hello World程序之所以是入门必读必会,就是因为其代码量少,简单易懂.但我觉得,还应该做到功能丰富, ...

随机推荐

  1. 004_软件安装之_Altium Designer

    文件中有软件简单视频教程,安装有pdf教程 链接:https://pan.baidu.com/s/1ow-OHdsPuAyXCevjCVqEsg 提取码:l2rt 复制这段内容后打开百度网盘手机App ...

  2. 1-git的安装和基本使用

    说一下,我希望都要会用git,git很好用, 代码管理,多人合作开发一个项目,版本记录等等 https://gitee.com/    去上面注册一个账户 https://git-scm.com/do ...

  3. Redis学习之一--基础知识

    一.定义 REmote DIctionary Server(Redis) 是一个以字典结构存储数据的key-value存储系统:使用ANSI C语言编写.遵守BSD协议.支持网络.可基于内存亦可持久化 ...

  4. try except else finally

    try..except..else没有捕获到异常,执行else语句 try..except..finally不管是否捕获到异常,都执行finally语句

  5. NNDL练习——Numpy的简单使用

    总结自nndl_exercise Numpy导入 import numpy as np 数组/矩阵的创建 a=np.array([1,2,3]) b=np.array([[1,2],[3,4]]) c ...

  6. GO 跟C++/C差异

    规范的语法(不需要符号表来解析) 垃圾回收(独有) 无头文件 明确的依赖 无循环依赖 常量只能是数字 int和int32是两种类型 字母大小写设置可见性(letter case sets visibi ...

  7. PHPStorm 快捷键大全(Win/Linux/Mac)

    下面的-符号记得改成 ‘`’,markdown 语法会转义.使用频率是我自己为准.仅供参考   Mac 符号 符号 解释 ⌘ Command ⇧ Shift ⌃ Control ↩ Enter/Ret ...

  8. Flutter移动电商实战 --(45)详细页_说明区域UI编写

    pages/details_page/details_expain.dart 详情页面引用组件 效果展示: 最终代码: import 'package:flutter/material.dart'; ...

  9. Windows安装Centos7双系统后Windows启动项消失

    原文: https://www.cnblogs.com/xinglichao/p/9999049.html https://blog.csdn.net/yingzinanfei/article/det ...

  10. nginx php-fpm安装配置 CentOS编译安装php7.2

    CentOS编译安装php7.2 介绍: 久闻php7的速度以及性能那可是比php5系列的任何一版本都要快,具体性能有多好,建议还是先尝试下再说.如果你是升级或新安装,那你首先需要考虑php7和程序是 ...