一、简介

Async/Await在.Net Core中真的是无处不在,到处都是异步操作,那为什么要用?有什么作用?别人说能提升性能?网上一堆文章看的绕晕了也没说清楚,

所以这里从理论,实践,原理一个个解开这些疑问。

二、Async/Await有什么用?

1.Async/Await用法示例

用法很简单,这里就不详细说具体怎么用了,只提供一个示例,我们的目标是研究它的作用。

 public class AsyncAwaitTest
{
public void Start()
{
Console.WriteLine($"aaa,线程Id:{Thread.CurrentThread.ManagedThreadId}");
AsyncMethod();
Console.WriteLine($"eee,线程Id:{Thread.CurrentThread.ManagedThreadId}");
Console.ReadLine();
}
public async Task<bool> AsyncMethod()
{
Console.WriteLine($"bbb,线程Id:{Thread.CurrentThread.ManagedThreadId}");
await Task.Run(() => { Thread.Sleep(500);
Console.WriteLine($"ccc,线程Id:{Thread.CurrentThread.ManagedThreadId}");
});
Console.WriteLine($"ddd,线程Id:{Thread.CurrentThread.ManagedThreadId}");
return true;
}
}

2.async/await的特点

1)不会阻塞线程

从示例的执行顺序,可以看出,当执行async/await方法时,主线程遇到await关键字,主线程就返回执行“eee”,然后释放,而不是等待,新开了一个子线程6执行另外的业务,await前面的方法还是主线程执行,await后面的方法,等线程6执行完了再继续执行。

2)同步的方式写异步

虽然是用了异步,但还是等待执行结果再往下执行,执行流程是同步的。

3.async/await能提升性能吗?

这个应该是大家最关心的问题了。

能提升单个请求的性能吗?

答案是不能的。很明显看的到,await等待了结果再执行后面的逻辑,还是串行的,执行完该多少秒还是多少秒, 中间还切换线程去处理了,相比同步来说还多了切换线程的损耗。

那async/await的意义何在?

在于多请求并发处理,且资源有限的时候,能增加吞吐量(单位时间处理的请求),增加cpu的利用率。

简单说就是有10个线程,每个线程的速度没有提升,然后居然QPS能提升?!

先来看一段微软官网的描述

  此模型可很好地处理典型的服务器方案工作负荷。由于没有专用于阻止未完成任务的线程,因此服务器线程池可服务更多的Web请求。

  考虑使用两个服务器:一个运行异步代码,一个不运行异步代码。对于本例,每个服务器只有5个线程可用于服务器请求。此字数太小,不切实际,仅供演示。

  假设这两个服务器都接收6个并发请求。每个请求执行一个I/O操作。未运行异步代码的服务器必须对第6个请求排队,直到5个线程中的一个完成了I/O密集型工作

并编写了响应。此时收到了第20个请求,由于队列过长,服务器可能会开始变慢。

  运行有异步代码的服务器也需要对第6个请求排队,但由于使用了async和await,I/O密集型工作开始时,每个线程都会得到释放,无需等到工作结束。

收到第20个请求时,传入请求队列将变得很小(如果其中还有请求的话),且服务器不会慢。

  尽管这是一个人为想象的示例,但现实世界中其工作方式与此类似。事实上,相比服务器将线程专用于接收到的每个请求,使用async和await能够使

服务器处理一个数量级的请求。

  注意上面官网描述的I/O密集型。什么样的是I/O密集型呢?,就是cpu性能必硬盘内存好太多,大部分时间都是cpu在等IO的读写操作。例如读文件,读文件的时候是不需要cpu参与的,只需要发一个命令给硬盘,硬盘读完文件会再通知cpu继续处理,这种叫DMA技术

  DMA(Direct Memory Access,直接存储器访问) 是所有现代电脑的重要特色,它是指一种高速的数据传输操作,允许在外部设备和存储器之间直接读写数据,既不通过cpu,也不需要cpu干预。

  这个时候异步就显出它的优势来了,比如读文件需要1s,如果是同步操作,那个就有一个线程在等1s在往下执行。如果是异步的,读文件的时候,这个线程就释放了,等读完文件,硬盘通知cpu再

派一个线程接着处理,那中间的1秒,原来的线程就可以去处理其他请求了。

4.代码对照说明

public class HomeController : Controller
{
/// <summary>
/// 同步请求
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
public string GetData()
{
var result = System.IO.File.ReadAllBytes(@"F:\package\package.rar");
return "ok";
} /// <summary>
/// 异步请求
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
public async Task<string> GetDataAsync2()
{
var result = await System.IO.File.ReadAllBytesAsync(@"F:\package\package.rar");
return "ok";
}
}

同步请求的流程为

可以看出,硬盘在读取文件时,线程是在等待的,这时候线程1在这1s中是不工作的,空等状态。

异步请求的流程为

异步请求时,线程1遇到await关键字,发出命令就返回,然后释放掉了,硬盘读完数据会通知cpu,这时cpu派一个新的线程去接着处理,

因此,读文件的这1s,线程1可以去处理其它请求了,没有空等,这就是提高了cpu的利用率,单位时间内处理的请求数就变大了。

cpu密集型的异步是不能提高QPS的,下面代码就是cpu密集型的。

cpu密集型:计算密集型,硬盘、内存性能比cpu好很多,或不太需要访问I/O设备。

     /// <summary>
/// 异步请求
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
public async Task<string> GetDataAsync2()
{
await Task.Run(() => {
Thread.Sleep(100);//模拟业务处理耗时
});
return "ok";
}

这里前面主线程遇到await虽然释放了,但await里面又有一个线程接着工作,cpu(线程并没有空闲)

I/O密集型中IO的操作有哪些呢?

文件读写、http请求、数据库请求、redis请求。。。等等。

 开发中哪些推荐用异步呢?

Web开发推荐、有Async的API的,Action、Filter、数据库访问、中间件等等。。。

.Net Core中无处不在的Async/Await是如何提升性能的?的更多相关文章

  1. 我也来说说C#中的异步:async/await

    序 最近看了一些园友们写的有关于异步的文章,受益匪浅,写这篇文章的目的是想把自己之前看到的文章做一个总结,同时也希望通过更加通俗易懂的语言让大家了解"异步"编程. 1:什么是异步 ...

  2. ASP.NET Core Web 应用程序系列(四)- ASP.NET Core 异步编程之async await

    PS:异步编程的本质就是新开任务线程来处理. 约定:异步的方法名均以Async结尾. 实际上呢,异步编程就是通过Task.Run()来实现的. 了解线程的人都知道,新开一个线程来处理事务这个很常见,但 ...

  3. C#异步中的Task,async,await

    class Program { static void Main(string[] args) { Console.WriteLine("我是主线程,线程ID:{0}", Thre ...

  4. .Net Core中使用ref和Span<T>提高程序性能

    一.前言 其实说到ref,很多同学对它已经有所了解,ref是C# 7.0的一个语言特性,它为开发人员提供了返回本地变量引用和值引用的机制. Span也是建立在ref语法基础上的一个复杂的数据类型,在文 ...

  5. 浅谈C#中的 async await 以及对线程相关知识的复习

    C#5.0以后新增了一个语法糖,那就是异步方法async await,之前对线程,进程方面的知识有过较为深入的学习,大概知道这个概念,我的项目中实际用到C#异步编程的场景比较少,就算要用到一般也感觉T ...

  6. 【TypeScript】如何在TypeScript中使用async/await,让你的代码更像C#。

    [TypeScript]如何在TypeScript中使用async/await,让你的代码更像C#. async/await 提到这个东西,大家应该都很熟悉.最出名的可能就是C#中的,但也有其它语言也 ...

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

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

  8. [原创.数据可视化系列之十二]使用 nodejs通过async await建立同步数据抓取

    做数据分析和可视化工作,最重要的一点就是数据抓取工作,之前使用Java和python都做过简单的数据抓取,感觉用的很不顺手. 后来用nodejs发现非常不错,通过js就可以进行数据抓取工作,类似jqu ...

  9. Async/Await替代Promise的6个理由

    译者按: Node.js的异步编程方式有效提高了应用性能:然而回调地狱却让人望而生畏,Promise让我们告别回调函数,写出更优雅的异步代码:在实践过程中,却发现Promise并不完美:技术进步是无止 ...

随机推荐

  1. mongodb中oplogsize大小设置

    1 oplogsize大小配置: 2 mongodb副本集构建的高可用方案,最少需要三个节点,一个主节点master,一个从节点slave,一个选举仲裁节点arbiter.当主节点奔溃的时候,仲裁节点 ...

  2. 实用的linux 命令

    1. 查看当前文件夹下文件或文件夹所占磁盘的大小 du -sh *|sort -rh 2. 查找某个进程号,脚本或程序所在目录的方法 ll /proc/进程id 3. awk 的用法 (1)累加: a ...

  3. ApacheCN 编程/大数据/数据科学/人工智能学习资源 2019.12

    公告 我们的所有非技术内容和活动,从现在开始会使用 iBooker 这个名字. "开源互助联盟"已终止,我们对此表示抱歉和遗憾.除非特地邀请,我们不再推广他人的任何项目. 公众号自 ...

  4. Java编程中标识符注意点以及注释

    标识符注意点 所有的标识符都应该以字母(A-Z或者a-z),美元符($),或者下划线(_)开始 首字符之后可以是字母(A-Z或者a-z),美元符($),下划线(_)或数 字的任何字符组合 不能使用关键 ...

  5. X000001

    一些相互无关联的题目的集合 都是码量不大,略有思维难度的题 做起来还是很舒适的 P6312 [PA2018]Palindrom 空间限制很小,不足以存下整个字符串,故暴力判断不可行. 考虑使用字符串哈 ...

  6. CF1270G Subset with Zero Sum

    首先一定要从每个数的范围 \(i - n \le a_i \le i - 1\) 入手,最开始是这样一个想法,不难发现对于每个 \(i\) 都能选 \(n\) 个数,并且能选的右端点在 \(i - 1 ...

  7. linux+nginx+tomcat负载均衡,实现session同步

    第一部分:nginx反向代理tomcat 一.软件及环境 软件 系统 角色 用途 安装的软件 ip地址 Centos6.5x86_64 nginx 反向代理用户请求 nginx 172.16.249. ...

  8. BGP路由协议(Border Gateway Protocol)

    BGP路由协议(Border Gateway Protocol) 目录 BGP路由协议(Border Gateway Protocol) 一.BGP概述 1.自治系统(AS,autonomous sy ...

  9. Shell之awk

    Shell之awk 目录 Shell之awk 一.awk概述 1. awk的工作原理 2. 命令格式 3. awk常见的内建变量(可直接用) 二.操作实例 1. 按行输出文本 2. 按字段输出文本 3 ...

  10. C#后台去除HTML标签

    public string NoHTML(string Htmlstring) { //删除脚本 Htmlstring = Regex.Replace(Htmlstring, @"<s ...