【.NET Core】深入理解async 和 await 理解

【.NET Core】深入理解async 和 await 理解

文章目录

  • 【.NET Core】深入理解async 和 await 理解
    • 一、概述
    • 二、async异步执行机制理解
    • 三、`async`与`await`应用
      • 3.1 `async`与`await`简单应用
      • 3.2 带有返回值`async`与`await`应用
    • 四、`async`和`await`中常见问题总结
      • 4.1 当方法用async标识时,编译器主要做了什么?
      • 4.2 当方法用async标识时,是不是所有调用者都将是异步?
      • 4.3 当方法用async标识时,是否会引起方法的调用会被添加到线程池队列中或者是创建一个新的线程呢?
      • 4.4 参数为什么不能使用ref和out关键字
      • 4.5 await关键字背后发生了什么
  • 五、总结

在这里插入图片描述

一、概述

asyncawait是C#5.0时代引入异步编程的核心关键字。通过使用异步编程,你可以避免性能瓶颈并增强程序响应能力。但是,编写异步应用程序的传统技术可能比较复杂,使异步编程难编写,调试和维护。

C#中的asyncawait关键字是异步编程的核心。通过这两个关键字,可以使用.NET Framework,.NET Core或Windows运行时中的资源,轻松创建异步方法。使用async关键字定义的异步方法简称为”异步方法“。

二、async异步执行机制理解

  • 在C#中,async标记了一个包含异步执行的函数,通过async的函数若在主线程中直接调用,则函数一开始扔在主线程中执行。
  • async标记的函数内部必须包含await标记需要异步执行的函数,若当前函数在主线程中直接调用,则await标记当前的代码在主线程中执行,await标记后的代码在其异步子线程中执行。
  • async标记的函数返回值必须为voidTaskTask<TResult>类型,可以理解为async标记的函数返回的是null,即将执行的任务带返回结果的即将执行的任务
  • async标记的函数可以继续往下调用async标记函数。

三、asyncawait应用

3.1 asyncawait简单应用

internal class Program
{static void Main(string[] args){Method1();Method2();Console.ReadKey();}public static async Task Method1(){await Task.Run(() =>{for (int i = 0; i < 30; i++){Task.Delay(100);Console.WriteLine(" Method 1");}});}public static void Method2(){for (int i = 0; i < 25; i++){Task.Delay(80);Console.WriteLine(" Method 2");}}
}

从上面代码运行结果可以看出,Method1和Method2相互并没有依赖关系,Method1和Method2并不是在等待对方完成。

3.2 带有返回值asyncawait应用

static void Main(string[] args)
{callMethod();Console.ReadKey();
}
public static async void callMethod()
{Task<int> task = Method1();Method2();int count = await task;Method3(count);
}
public static async Task<int> Method1()
{int count = 0;await Task.Run(() =>{for (int i = 0; i < 20; i++){Console.WriteLine(" Method 1");count += 1;}});return count;
}public static void Method2()
{for (int i = 0; i < 25; i++){Console.WriteLine(" Method 2");}
}
public static void Method3(int count)
{Console.WriteLine("Total count is " + count);
}

在上面给出的代码中,Method 3需要一个参数,即Method 1的返回类型。在这里,await关键字对于等待Method 1任务的完成起着至关重要的作用。

四、asyncawait中常见问题总结

4.1 当方法用async标识时,编译器主要做了什么?

  • 告诉编译器这个方法里面可能会用到await关键字来标识该方法是异步的,如此之后,编译器将会在状态机中编译此方法。接着该方法执行到await关键字时会处于挂起的状态直到该异步动作完成后才恢复继续执行方法后面的动作。
  • 告诉编译器解析出方法的结果到返回类型中,比如说Task或者Task,也就是说将返回值存储到Task中,如果返回值为void那么此时应该会将可能出现的异常存储到上下文中。

4.2 当方法用async标识时,是不是所有调用者都将是异步?

当将方法用async标识时且返回值为void或者Task或者Task,此时该方法会在当前线程中一直同步执行。

用async标识方法并不会影响方法运行完成是否是同步或者异步,相反,它能够将方法划分成多块,有可能有些在异步中运行,以至于这些方法是异步完成的,而划分异步和同步方法的边界就是使用await关键字。也就是说如果在方法中未用到await关键字时则该方法就是一整块没有所谓的划分,会在同步中运行,在同步中完成。

4.3 当方法用async标识时,是否会引起方法的调用会被添加到线程池队列中或者是创建一个新的线程呢?

显然不是这样,当用async标识方法时只是显示告诉编译器在该方法中await关键字可能会被用到,当执行到await关键字开始处于挂起的状态知道异步动作执行完成才恢复(异步操作是在状态机中【有关状态机请看这里:Async和Await异步编程的原理】完成,完成后此时才会创建一个线程),这也就是为什么在方法中方法用async标识如果没有用到await关键字IDE会发出警告的原因。

到了这里我们可以得出结论:无论方法是同步还是异步都可以用async关键字来进行标识,因为用async标识只是显示表明在该方法内可能会用到await关键字使其变为异步方法,而且将该异步方法进行了明确的划分,只有用了await关键字时才是异步操作,其余一并为同步操作。

4.4 参数为什么不能使用ref和out关键字

我们知道用ref和out关键字不过是为了在方法里面改变其值,也就是是当同步完成时我们期望被ref或者out关键字修饰的值会被设置,但是它们可能在异步完成时或者之后才会被设置达不到我们预期,所以在异步方法中不能用ref和out关键字。

4.5 await关键字背后发生了什么

await关键字是这样用的

await Task.Run(() => "goyeer");

此时背后究竟发生了什么呢?我们上述也说过异步动作时在状态机中完成,当执行到这里时,编译器会自动生成代码来检测该动作是否已经完成,如果已经完成则继续同步执行await关键字后面的代码,通过判断其状态机状态若未完成则会挂起一个继续的委托为await关键字的对象直到完成为止,调用这个继续动作的委托重新进入未完成的这样一个方法。

五、总结

本节我们详细讲述了async和await关键字的使用和一些基本原理以及解释其原因,希望通过对本文的学习,对大家能够更好的去理解异步。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/690119.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

7条策略,提升可视化大屏的科技感,值得收藏。

以下是从设计角度上提升科技感的几条建议&#xff1a; 使用现代化的字体&#xff1a; 选择现代化的字体能够让大屏幕看起来更加科技感。比如&#xff0c;Sans-serif字体、Roboto字体、Lato字体等都是现代化的字体。 设计简洁、清晰的图表&#xff1a; 图表是可视化大屏设计中…

端口号被占用怎么解决

1、快捷键"winR"打开运行&#xff0c;在其中输入"cmd"命令&#xff0c;回车键打开命令提示符。 2、进入窗口后&#xff0c;输入"netstat -ano"命令&#xff0c;可以用来查看所有窗口被占用的情况。 比如端口号为7680的端口被占用了&#xff0c…

一次失败的面试经历:我只想找个工作,你却用面试题羞辱我

金三银四就要来了&#xff0c;即将又是一波求职月&#xff0c;面对跳槽的高峰期&#xff0c;很多软件测试人员都希望能拿一个满意的高薪offer&#xff0c;但是随着招聘职位的不断增多&#xff0c;面试的难度也随之加大&#xff0c;而面试官更是会择优录取 小王最近为面试已经焦…

循环测试之旅 —— 深度解析Pytest插件 pytest-repeat!

在软件开发中&#xff0c;测试的重要性不言而喻。而为了提高测试的鲁棒性和可靠性&#xff0c;Pytest插件 pytest-repeat 应运而生。这个插件可以帮助你轻松实现测试用例的循环运行&#xff0c;以更全面地评估代码的稳定性。本文将深入介绍 pytest-repeat 插件的基本用法和实际…

msvcp140.dll丢失要怎么处理的一些解决方法,分享一些解决办法

在Windows操作系统中&#xff0c;有时候我们会遇到一些dll文件丢失或损坏的问题。其中一个常见的错误是"找不到msvcp140.dll"。这个错误会导致一些应用程序无法正常运行&#xff0c;给我们的电脑使用带来了很大的困扰。不用担心&#xff0c;今天我们就来说说由于找不…

OpenAI视频生成模型Sora的全面解析:从ViViT、扩散Transformer到NaViT、VideoPoet

前言 真没想到&#xff0c;距离视频生成上一轮的集中爆发(详见《视频生成发展史&#xff1a;从Gen2、Emu Video到PixelDance、SVD、Pika 1.0、W.A.L.T》)才过去三个月&#xff0c;没想OpenAI一出手&#xff0c;该领域又直接变天了 自打2.16日OpenAI发布sora以来(其开发团队包…

《剑指Offer》笔记题解思路技巧优化 Java版本——新版leetcode_Part_4

《剑指Offer》笔记&题解&思路&技巧&优化_Part_4 &#x1f60d;&#x1f60d;&#x1f60d; 相知&#x1f64c;&#x1f64c;&#x1f64c; 相识&#x1f622;&#x1f622;&#x1f622; 开始刷题1. LCR 148. 验证图书取出顺序——栈的压入、弹出序列2. LCR 14…

简单贪吃蛇模拟(C语言版本·)

简单贪吃蛇模拟&#xff08;C语言版本&#xff09; 一、所需win32 API知识二、游戏逻辑实现 一、所需win32 API知识 1.在这儿&#xff0c;直接弱化概念&#xff0c;把在贪吃蛇中用到的API知识说一下&#xff01;  1.1用cmd命令来设置控制台窗口的长宽   1.2.用title 指令…

如何使用Pycharm中的image模块以及导入打开图片(属性)

在学习pytorch深度学习的过程中&#xff0c;通常会使用到大量的数据集&#xff0c;包括训练集和测试集。 以下是pytorch加载数据集的流程&#xff1a; 在notebook中使用help方法查看Dataset类的功能以及操作&#xff1a; 使用dataset需要继承Dataset父类 重写__getitem__方法和…

更换笔记本电脑内存条

写在前头 本人笔记本电脑早年购买&#xff0c;随着学习工作量的增大&#xff0c;我在使用电脑时往往需要同时打开多个软件&#xff0c;这时电脑的表现就难以言论了。虽然这个电脑在我的手中表现出其“志在千里”的鸿志&#xff08;毕竟它主人是谁里&#xff09;&#xff0c;但…

前端秘法基础式(CSS)(第二卷)

目录 一.字体 1.字体的设置 2.字体的颜色 2.1预定义的颜色值 2.2十六进制 2.3rgb表示法 3.字体粗细及样式 4.文本 4.1text-align 4.2text-indent 4.3text-decoration 二.背景属性 三.圆角矩形 四.元素显示模式 五.盒模型 六.弹性布局 七.Chrome调试工具 一.字…

普通人steam搬砖到底能不能做,一定谨记这4点

steam/csgo搬砖项目拥有小投资收益稳定的特点&#xff0c;多搬多赚&#xff0c;这个项目已存在很多年&#xff0c;是非常老牌的阳光项目&#xff0c;很多人比较关心普通人steam搬砖到底能不能做&#xff0c;这里想提醒你谨记这4点。 1&#xff1a;steam/csgo搬砖项目不需要玩游…

java.sql.SQLException: No operations allowed after statement closed.

背景 某天下午&#xff0c;客服反馈线上服务出现问题&#xff0c;不能分配了。于是我登录到系统上&#xff0c;进行同样的操作发现也不行。当然同时我已经登录到服务器打开了日志&#xff0c;发现报错了&#xff0c;下面就是日志的错误信息&#xff1a; java.sql.SQLExceptio…

AI嵌入式K210项目(29)-模型加载

文章目录 前言一、下载部署包二、C部署三、搭建文件传输环境四、文件传输五、调试六、MicroPython部署总结 前言 上一章节介绍了如何进行在线模型训练&#xff0c;生成部署包后&#xff0c;本章介绍加载模型&#xff1b; 一、下载部署包 训练结束后&#xff0c;在训练任务条…

基于ESP32+Platformio的物联网RTOS_SDK-CC_Device

本项目基于ESP32以及Platformio平台开发&#xff0c;请自行查阅如何配置这个环境 开源gitee地址&#xff1a;cc_smart_device 如果愿意贡献项目or提出疑问和修改的&#xff0c;请在gitee上提issue 项目里的mqtt服务器是公共的 请大家最好换成私有的 否则容易收到其他用户的错误…

mybatis 基础入门使用

1、mybatis 简介 1.1、mybatis 特性 MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架&#xff1b; MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集&#xff1b; MyBatis可以使用简单的XML或注解用于配置和原始映射&#xff0c;将接口和…

【Java面试】MongoDB

目录 1、mongodb是什么&#xff1f;2、mongodb特点什么是NoSQL数据库&#xff1f;NoSQL和RDBMS有什么区别&#xff1f;在哪些情况下使用和不使用NoSQL数据库&#xff1f;NoSQL数据库有哪些类型?启用备份故障恢复需要多久什么是master或primary什么是secondary或slave系列文章版…

【shell】2、Makefile

文章目录 一、变量1.1 定义简单变量1.2 定义数组1.3 引用变量1.4 规则中定义变量 一、变量 1.1 定义简单变量 用变量名 值的语法来定义变量。这些变量可以用于存储命令、文件名、目录路径等信息&#xff0c;以便在Makefile规则中重复使用 # 定义一个变量 VAR_NAME value# …

【医学大模型】MEDDM LLM-Executable CGT 结构化医学知识: 将临床指导树结构化,便于LLM理解和应用

MEDDM LLM-Executable CGT 结构化医学知识: 将临床指导树结构化&#xff0c;便于LLM理解和应用 提出背景对比传统医学大模型流程步骤临床指导树流程图识别临床决策支持系统 总结解决方案设计数据收集与处理系统实施临床决策支持 提出背景 论文&#xff1a;https://arxiv.org/p…

什么是DoS和DDoS攻击?

DoS和DDoS攻击是两种常见的网络攻击方式&#xff0c;它们通过向目标服务器发送大量的无效或高流量的网络请求&#xff0c;从而耗尽服务器的资源&#xff0c;使其无法正常处理有效的请求。 DoS攻击是一种单点攻击方式&#xff0c;通常是通过向目标服务器发送大量的请求&#x…