【.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关键字的使用和一些基本原理以及解释其原因,希望通过对本文的学习,对大家能够更好的去理解异步。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

(每日持续更新)信息系统项目管理(第四版)(高级项目管理)考试重点整理第10章 项目进度管理(六)

博主2023年11月通过了信息系统项目管理的考试&#xff0c;考试过程中发现考试的内容全部是教材中的内容&#xff0c;非常符合我学习的思路&#xff0c;因此博主想通过该平台把自己学习过程中的经验和教材博主认为重要的知识点分享给大家&#xff0c;希望更多的人能够通过考试&a…

跨境云手机如何简化tiktok运营流程

如今&#xff0c;tiktok已经成为世界范围内都非常流行的社交媒体平台。然而在大多数情况下&#xff0c;由于网络原因&#xff0c;tiktok无法在国内使用&#xff0c;但依然有越来越多的人注册tiktok号码、建立tiktok矩阵。原因是tiktok仍然有大量的流量可供商业使用&#xff0c;…

day04-股票K线功能实现

股票K线功能实现 今日目标 1.理解股票T和T-1概念&#xff0c;实现成交量对比功能; 2.理解个股涨跌幅度统计功能; 2.1 分析业务&#xff0c;SQL落地; 2.2 完善不存在数据的区间默认回显功能; 3.理解个股分时线业务&#xff0c;并实现功能; 4.理解个股日K线业务&#xff0c;并实…

使用傅里叶实现100倍的压缩效果(附Python源码)

傅里叶变换&#xff08;Fourier Transform&#xff09;是一种将一个函数&#xff08;在时间或空间域&#xff09;转换为另一个函数&#xff08;在频率域&#xff09;的数学变换方法。它在信号处理、图像处理、通信等领域有广泛应用。 实现过程 将傅里叶系数核心的1%保留&…

从零开始手写mmo游戏从框架到爆炸(十五)— 命令行客户端改造

导航&#xff1a;从零开始手写mmo游戏从框架到爆炸&#xff08;零&#xff09;—— 导航-CSDN博客 到现在&#xff0c;我们切实需要一个客户端来完整的进行英雄选择&#xff0c;选择地图&#xff0c;打怪等等功能。所以我们需要把之前极为简陋的客户端改造一下。 首先…

0成本部署github前端项目流程

0成本部署github纯前端项目流程 对业内来说应该是一个比较常规的操作&#xff0c;对于新手来说进行过一次应该就很难忘记了&#xff0c;但很多人仍然是不会的&#xff0c;认为部署项目很难&#xff0c;很专业&#xff0c;其实现在由于这些厂商的努力&#xff0c;大众&#xff…

js设计模式:装饰者模式

作用: 可以给原有对象的身上添加新的属性方法 可以让对象或者组件进行扩展 示例: class Person{constructor(name,selfSkill){this.name namethis.selfSkill selfSkill}run 会走路}//所有人类都有的共同特性和技能let wjt new Person(王惊涛,写代码)let mashi new Pers…

Python实现KDJ指标计算:股票技术分析的利器系列(3)

Python实现KDJ指标计算&#xff1a;股票技术分析的利器系列&#xff08;3&#xff09; 介绍算法解释 代码rolling函数介绍计算LLV&#xff08;最低价最小值&#xff09;和HHV&#xff08;最高价最大值&#xff09;计算RSV计算SMA&#xff08;简单移动平均&#xff09; 完整代码…

micro-app以UMD js链接方式引入使用

npm 下载好micro-zoe/micro-app后&#xff0c;找到index.umd.js&#xff1a; 新建一个测试html&#xff0c;引入并使用&#xff1a; 参考&#xff1a; 微组件实践 - 掘金

八、计算机视觉-边界填充

文章目录 前言一、原理二、具体的实现 前言 在Python中使用OpenCV进行边界填充&#xff08;也称为zero padding&#xff09;是一种常见的图像处理操作&#xff0c;通常用于在图像周围添加额外的像素以便进行卷积或其他操作。下面是使用OpenCV进行边界填充的基本原理和方法 一…

答题抽奖活动怎么做_一场智慧与幸运的碰撞

答题抽奖&#xff0c;知识变现&#xff0c;一场智慧与幸运的碰撞&#xff01; 在这个信息爆炸的时代&#xff0c;如何吸引人们的注意力&#xff0c;成为每个营销者都需要面对的挑战。而答题抽奖活动&#xff0c;以其独特的魅力&#xff0c;正成为越来越多品牌吸引用户、提升用…

智能无人仓|加快步伐 河北沃克HEGERLS将突破与创新“常态化”

物流的发展涉及工业、商业各个领域&#xff0c;涵盖原材料&#xff0c;生产成品从起点到终点的全过程&#xff0c;在室内物流操作上涵盖了收、发、存、拣等作业。近年来&#xff0c;由于人工成本的提高&#xff0c;基础劳动力取得的难度不断地加大&#xff0c;自动化和智能化逐…

pytest 框架自动化测试

随笔记录 目录 1. 安装 2. 安装pytest 相关插件 2.1 准备阶段 2.2 安装 2.3 验证安装成功 3. pytest测试用例的运行方式 3.1 主函数模式 3.1.1 主函数执行指定文件 3.1.2 主函数执行指定模块 3.1.3 主函数执行某个文件中的某个类、方法、函数 3.1.4 主函数执行生…

『运维备忘录』之 SSH 命令详解

运维人员不仅要熟悉操作系统、服务器、网络等知识&#xff0c;甚至对于开发相关的也要有所了解。很多运维工作者可能一时半会记不住那么多命令、代码、方法、原理或者用法等等。这里我将结合自身工作&#xff0c;持续给大家更新运维工作所需要接触到的知识点&#xff0c;希望大…

C++Qt:noteBookPro_01

一、创建项目 选择Qt Widgets 常用的是QWidgets和MainWindow。两者的区别&#xff1a; QWidgets用于简单的窗口&#xff0c;没有内置的菜单栏、工具栏和状态栏。适用于简单专用的应用程序&#xff0c;不需要复杂的界面组件。 MainWindow是包含完整的菜单栏、工具栏和状态栏的主…

入门级10寸加固行业平板—EM-I10J

亿道信息以其坚固耐用的智能终端设备而闻名&#xff0c;近日发布了一款理想入门级 10 英寸加固平板电脑—I10J。 EM-I10J​​ 这是一款 10 英寸的平板电脑&#xff0c;主要运行 Windows 10操作系统&#xff0c;带有硬化塑料外壳&#xff0c;具有 IP65 防水防尘功能和 MIL-STD 8…

unity学习(19)——客户端与服务器合力完成注册功能(1)入门准备

逆向服务器用了三天的时间&#xff0c;但此时觉得一切都值&#xff0c;又可以继续学习了。 服务器中登录请求和注册请求由command变量进行区分&#xff0c;上一层的type变量都是login。 public void process(Session session, SocketModel model) {switch (model.Command){ca…

nvm安装配置环境

前言 对于前端开发人员来说&#xff0c;多个项目可能用的不同的node版本&#xff0c;如何方便快速的转换版本&#xff0c;nvm版本管理工具的出现&#xff0c;解决这个问题。 实战 1. 搜索nvm版本&#xff0c;我用的1.1.2&#xff0c;下载后直接安装。 2.在d盘建立nvm空文件…

网络IO模型

前言 本篇博客主要讲解一下网络IO模型。我们常见的网络模型分为 阻塞IO模型&#xff0c;非阻塞IO模型&#xff0c;IO复用模型&#xff0c;信号驱动IO模型&#xff0c;异步IO模型。下面我详细的介绍一下这五个IO模型。 阻塞IO模型 ​ 所谓阻塞IO就是当应用A发起读取数据申请时&…

Nginx 正向代理、反向代理

文章目录 前言1. 正向代理1.1 概念1.2 逻辑图1.3 使用场景 2. 反向代理2.1 概念2.2 逻辑图2.3 使用场景 前言 正向代理主要是用来解决访问限制问题&#xff1b;反向代理则是提供负载均衡、安全防护等作用 1. 正向代理 1.1 概念 正向代理是一个位于客户端和目标服务器之间的代理…