async、await原理

async的方法会被C#编译器编译成一个类,会根据 await 调用切分为多个状态。对 async 方法的调用会被拆分为对 MoveNext 的调用。和状态机有关,还没有理清楚,先看其他人的解密吧:解密async await 原理(.net)

await 看似“等待”,但经过编译后,其实没有“wait”

为什么说 await 没有等待呢?

因为 await 调用“等待”期间,.Net 会把当前的线程返回给线程池,等异步方法调用执行完毕后,框架会从线程池再取出一个线程执行后续的代码(PS:造成了线程切换)。

// *** Main *** /
int threadId = Thread.CurrentThread.ManagedThreadId;
Console.WriteLine($"第一次打印:{threadId}");  // 打印当前线程 Idawait AsyncProgramming.TestAsync();threadId = Thread.CurrentThread.ManagedThreadId;
Console.WriteLine($"第五次打印:{threadId}");// *** AsyncProgramming *** /
internal class AsyncProgramming
{public static async Task TestAsync(){int threadId = Thread.CurrentThread.ManagedThreadId;System.Console.WriteLine($"第二次打印:{threadId}");string path = @"D:\Temp";string fileName = "1.txt";string fullPath = Path.Combine(path, fileName);StringBuilder sb = new StringBuilder();for (int i = 0; i < 10000; i++){sb.Append("aaaa");}threadId = Thread.CurrentThread.ManagedThreadId;System.Console.WriteLine($"第三次打印:{threadId}");#region 耗时任务await File.WriteAllTextAsync(fullPath, sb.ToString());#endregionthreadId = Thread.CurrentThread.ManagedThreadId;System.Console.WriteLine($"第四次打印:{threadId}");}
}


可以看到前三次打印都是同一个线程,从 await 等待异步方法执行后面两次打印的是一个线程。由此可见,调用 await 执行语句确实把当前的线程给释放了(返回给线程池),调用完毕则又重新取出一个线程执行后续的代码(线程进行切换了)。

异步方法≠多线程

异步方法的代码并不会自动在新线程中执行,除非把代码放到新线程中执行。修改上面代码中关于写的部分:

internal class AsyncProgramming
{public static async Task TestAsync(){int threadId = Thread.CurrentThread.ManagedThreadId;System.Console.WriteLine($"第二次打印:{threadId}");string path = @"D:\Temp";string fileName = "1.txt";string fullPath = Path.Combine(path, fileName);StringBuilder sb = new StringBuilder();for (int i = 0; i < 10000; i++){sb.Append("aaaa");}threadId = Thread.CurrentThread.ManagedThreadId;System.Console.WriteLine($"第三次打印:{threadId}");File.WriteAllText(fullPath, sb.ToString());  // 修改的部分threadId = Thread.CurrentThread.ManagedThreadId;System.Console.WriteLine($"第四次打印:{threadId}");}
}

执行结果:

可以看到,同样是标记 async 的异步方法,但并没有创建新的线程,而是在同一个线程中执行。继续修改:

internal class AsyncProgramming
{public static async Task TestAsync(){int threadId = Thread.CurrentThread.ManagedThreadId;System.Console.WriteLine($"第二次打印:{threadId}");string path = @"D:\Temp";string fileName = "1.txt";string fullPath = Path.Combine(path, fileName);StringBuilder sb = new StringBuilder();for (int i = 0; i < 10000; i++){sb.Append("aaaa");}threadId = Thread.CurrentThread.ManagedThreadId;System.Console.WriteLine($"第三次打印:{threadId}");// 修改部分await Task.Run(() =>{File.WriteAllText(fullPath, sb.ToString());});threadId = Thread.CurrentThread.ManagedThreadId;System.Console.WriteLine($"第四次打印:{threadId}");}
}

我们通过Task.Run的方式创建了一个新的线程,在线程中执行了写的代码。由此可见,异步方法的却不等于多线程,只能说异步方法可能是多线程的。

异步方法

异步方法:使用 async 关键字修饰的方法。

  1. 异步方法的返回值一般都是Task<T>T才是真正的返回值类型
  2. 如果方法没有返回值,要把返回值声明为非泛型的Task
  3. 调用泛型方法时,通过await关键字,这样可以拿到泛型指定的T类型的返回值
  4. 异步方法具有“传递性”,一个方法中如果有 await 调用,则这个方法也必须修饰为 async

异步方法的命名通常以 Async 结尾

async、await关键字的使用简化了多线程开发,但是async、await ≠ “多线程”

异步编程思想:不等待

async 方法的缺点
  1. 异步方法会生成一个类,运行效率没有普通方法高(因为通过状态机 MoveNext 的方式调用)
  2. 可能会占用非常多的线程(其中发生了线程切换)

非必要情况下直接返回Task<T>类型,不使用async关键字标记
这样只是普通方法调用,运行效率更高,不会造成线程浪费

.Net 异步编程之async和await相关推荐

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

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

  2. python3 sleep 并发_python异步编程之asyncio(百万并发)

    点击上方蓝字关注我们 目录 [python 异步编程之 asyncio(百万并发)] 一.asyncio 二.aiohttp 前言:python 由于 GIL(全局锁)的存在,不能发挥多核的优势,其性 ...

  3. pythonasyncio并发编程实战_python异步编程之asyncio(百万并发)

    [python异步编程之asyncio(百万并发)] 前言:python由于GIL(全局锁)的存在,不能发挥多核的优势,其性能一直饱受诟病.然而在IO密集型的网络编程里,异步处理比同步处理能提升成百上 ...

  4. 异步编程之Promise(2):探究原理

    异步编程系列教程: (翻译)异步编程之Promise(1)--初见魅力 异步编程之Promise(2):探究原理 异步编程之Promise(3):拓展进阶 异步编程之Generator(1)--领略魅 ...

  5. 初探asp.net异步编程之await

    终于毕业了,也顺利进入一家期望的旅游互联网公司.27号入职.放肆了一个多月没写代码,好方啊. 另外一下观点均主要针对于await. 请先看这段话,来自async in C# 5.0.  接下来几个月的 ...

  6. python异步asy_Python 异步编程之asyncio【转载】

    一.协程的认识 协程(Coroutine),也可以被称为微线程,是一种用户态内的上下文切换技术. 简而言之,其实就是通过一个线程实现代码块相互切换执行.例如:deffunc1():print(1) . ...

  7. 异步编程(async 和 await)

    1.概念 异步编程是一项关键技术,可以直接处理多个核心上的I/O阻塞和并发操作 2.使用场景 对于存在IO密集型(例如从网路请求数据.访问数据库和写入到文件系统)和CPU密集型(例如大量的计算)的任务 ...

  8. 前端异步编程之Promise和async的用法

    传统的异步解决方案采用回调函数和事件监听的方式,而这里主要记录两种异步编程的新方案: ES6的新语法Promise ES2017引入的async函数 Generator函数(略) Promise的含义 ...

  9. Python3.7 高级编程之 async/await asyncio 事件循环的使用

    什么是事件循环: 事件循环是每个 asyncio 应用的核心. 事件循环会运行异步任务和回调,执行网络 IO 操作,以及运行子进程. 说简单点就是由于python是单线程的 程序在执行中会将所有任务放 ...

  10. JS异步编程之callback

    为什么 JS 是单线程? 众所周知,Javascript 语言的执行环境是"单线程"(single thread). 所谓"单线程",就是指一次只能完成一件任务 ...

最新文章

  1. Keepalived + LVS-NAT 实现高可用四层 TCP/UDP 负载均衡器
  2. Deep Metric Learning for Person Re-Identification
  3. LED驱动设计及实现
  4. 中北大学c语言程序设计作业答案,C语言程序设计
  5. 我在 GitHub 上看到了一个丧心病狂的开源项目!
  6. Struts自定义拦截器拦截器工作原理
  7. java类加载-ClassLoader双亲委派机制
  8. hibernate get() load() 区别
  9. docker --- 使用docker-compose.yml生成redis,并连接redis-cli
  10. 如何应对视觉深度学习存在的问题
  11. 派尼数据库连接池配置
  12. Ubuntu13.04配置优化(二)转贴
  13. 适合人工智能开发的5种最佳编程语言优缺点对比
  14. 新浪微博批量删除微博的方法
  15. 8个高质量免抠素材网站
  16. 用计算机处理文字单元设计,计算机应用基础单元设计62(处理图像).doc
  17. css不换行省略号 没作用,flex布局下,css设置文本不换行时,省略号不显示的解决办法...
  18. 为什么从看似稳定安逸的高校抑郁辞职?(不客观但真实)
  19. SCT2601TVBR、LMR16006XDDCR、MP2456GJ-Z参数
  20. 褚志刚——噪声源识别与定位

热门文章

  1. 安装prometheus 2.21.0
  2. 波哥学JAVA基础教程 5.1.2 封装方法
  3. 任天行网络安全管理系统
  4. 开源且强大的网络嗅探分析工具——Wireshark
  5. vues3中vuex的简单使用的两种方式
  6. 25. matplotlib
  7. A Dependency-Based Neural Network for Relation Classification(DepNN,2015)论文阅读笔记
  8. Goland 设置与配置
  9. 在macOS苹果电脑上安装Azure DevOps Server(TFS)代理
  10. uos-20sp1 龙芯系统 编译51版本火狐浏览器,公司有npapi插件 52版本后不支持