C# 细说async/await的用法

2023-11-19

目录

一,引言

二,实例演示

2.1 多线程同步执行下载任务,任务完成后通知

2.2 异步执行下载任务,任务完成后通知

三,async/await的用法

3.1 跨线程修改UI控件

3.2 异步获取数据


一,引言

首先先来区分一下,同步方法,异步方法和多线程:

  • 同步方法:调用时需要等待返回结果(相当于阻塞了该线程),才可以继续往下执行业务
  • 异步方法:调用时无须等待返回结果(等待时释放线程),可以继续往下执行业务
  • 多线程:在主线程之外开启一个新的线程去(增加线程,同步执行)执行业务

 关于async/await:

  1.  async和await关键字是C# 5.0时代引入的,它是一种异步编程模型
  2. 它们本身并不创建新线程,但可以在自行封装的async中利用Task.Run开启新线程
  3. 方法体中使用await,方法也必须声明为async(成对出现),如果没有await,async关键字也没有意义。

async/await的理解:

个人理解:await可以看着是代码执行的分裂点,当程序执行到await后面的语句时,首先系统会将当前的线程释放(回归线程池,其他程序可调用),并捕获当前上下文(打上标记),进入等待(注意:期间没有线程阻塞)。当await后语句执行完毕,根据标记点调用线程(从线程池随机捕获线程,有概率是原来的线程)执行下面的语句。

二,实例演示

2.1 多线程同步执行下载任务,任务完成后通知

static void Main(string[] args)
        {
            DownloadHandle();
            Console.ReadLine();
        }
        public static  void DownloadHandle()
        {
            Console.WriteLine("下载开始!->主线程ID:" + Thread.CurrentThread.ManagedThreadId);
            var t= Download();
            Task.WaitAll(t);
            Console.WriteLine("下载完成!->主线程ID:" + Thread.CurrentThread.ManagedThreadId);
        }
        public static Task Download()
        {
            return Task.Run(() =>
            {
                Console.WriteLine("下载线程ID:->" + Thread.CurrentThread.ManagedThreadId);
                Console.WriteLine("10%");
                Console.WriteLine("30%");
                Console.WriteLine("50%");
                Console.WriteLine("60%");
                Console.WriteLine("80%");
                Console.WriteLine("99%");
                Console.WriteLine("100%");
            });
        }

结果输出:

可以看的,在多线程下载任务时,通过Task.WaitAll(t) 等待线程执行完毕后,主线程一直处于阻塞状态。

2.2 异步执行下载任务,任务完成后通知

        static void Main(string[] args)
        {
            DownloadHandle();
            Console.ReadLine();
        }
        public static async void DownloadHandle()
        {
            Console.WriteLine("下载开始!->主线程ID:" + Thread.CurrentThread.ManagedThreadId);
            await Download();
            Console.WriteLine("下载完成!->主线程ID:" + Thread.CurrentThread.ManagedThreadId);
        }
        public static Task Download()
        {
            return Task.Run(() =>
            {
                Console.WriteLine("下载线程ID:->" + Thread.CurrentThread.ManagedThreadId);
                Console.WriteLine("10%");
                Console.WriteLine("30%");
                Console.WriteLine("50%");
                Console.WriteLine("60%");
                Console.WriteLine("80%");
                Console.WriteLine("99%");
                Console.WriteLine("100%");
            });
        }

可以看的,在异步下载任务时,主线程未被阻塞。

异步方法async/await的返回值类型一般都是Task或者Task<T>类型的,当返回值为Task时(即方法的返回值类型为void),我们可以直接return Task.Run(()=>{}),而不必await Task.Run(()=>{}),这样也可从一定程度上提高代码执行效率。另外,不推荐使用async 修饰void返回值,会有异常处理方面的问题。

三,async/await的用法

async/await并不能提升代码的执行速度,但可以提高响应能力(吞吐量),即使用异步方式在同一时间可以处理更多的请求。

  • 使用同步方式,线程会被耗时操作一直占用,直到耗时操作结束;
  • 使用异步方式,程序走到await关键字会立即return,释放线程,剩下的代码将放到一个回调,耗时操作完成时才会回调执行。

因此:

  • 对于计算密集型工作,使用多线程
  • 对于IO密集型工作,采用异步机制

从代码整体的架构设计来说,由于async/await语法容易使得程序被await传染,因此不要从最里面的方法启动线程,而是把启动线程的代码放到最外面,这样一来绝大部分方法就都不再需要用async修饰了,方法就都可以用正常的方式开发了。

3.1 跨线程修改UI控件

通过async/await的机制,可以非常简洁轻松的实现跨线程修改UI控件的问题,也不用使用Invoke。(因为本质上还是在原来的线程上修改的,还没有阻塞UI界面)

private async void button1_Click(object sender, EventArgs e)
        {
            var t = Task.Run(() => {
                Thread.Sleep(5000);
                return "Hello I am TimeConsumingMethod";
            });
            textBox1.Text = await t;
        }

3.2 异步获取数据

在写后端的数据异步处理时,通过async/await语法也可轻易实现,为了防止async/await语法传染,将启动线程的代码放在了最外层,这样在Click事件中就可以正常调用了,不用在增加async关键字了。

 private void button2_Click(object sender, EventArgs e)
        {
            AsyncFunc();
        }
        private async Task AsyncFunc()
        {
            DataTable dt = await FecthData();
            this.dataGridView1.DataSource = dt;
        }
        private async Task<DataTable> FecthData()
        {
            DataTable dt = null;
            await Task.Run(() =>
            {
                dt = new DataTable();
                dt.Columns.Add("id", typeof(int));
                dt.Columns.Add("name");
                for (int i = 0; i < 10000; i++)
                {
                    dt.Rows.Add(new object[] { i, "name" + i.ToString() });
                }
                Thread.Sleep(1000);
            });
            return dt;
        }

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C# 细说async/await的用法 的相关文章

  • 显示 div 内的用户名列表

    我是 jQuery 新手 在我的项目中 我创建了一个类User其中代码如下所示 static ConcurrentDictionary
  • 读取大文件并制作字典

    我有一个大文件 我需要读取它并从中制作字典 我希望这一切能够尽可能快 然而我的Python代码太慢了 这是一个显示问题的最小示例 首先制作一些假数据 paste lt seq 20000000 lt seq 2 20000001 gt la
  • 是否有可能将 *.pdb 文件包含到发布版本中以查看错误行号?

    我做了一个项目 所有设置都是默认的 当我在调试模式 构建配置 调试 下运行它并遇到异常时 它转储到我的自定义日志记录机制 其中包含错误行号 但是当我运行发布构建时 记录相同的异常 没有行号 只有方法抛出和记录调用堆栈 是否有可能在发布配置
  • 在异步请求中使用超时回调

    我之前问过这个问题 但我将用提出的解决方案来完成这个问题 并提出另一个问题 我正在使用这个类来进行异步网络请求 http msdn microsoft com en us library system net webrequest aspx
  • 使用 GCHandle 将大型结构数组从 C# unity 脚本传递到 C++ dll 在 C++ 函数执行后崩溃

    我想从 C unity 脚本将结构数组传递给 c 本机插件 我做了如下操作 我可以访问数据 但我的应用程序在执行 c 函数后崩溃 我不知道为什么 C side StructLayout LayoutKind Sequential publi
  • 如何部署包含第三方 DLL 文件的 C# 应用程序?

    首先 我对部署了解不多 我希望我的问题有意义 我需要将 C 应用程序安装 部署到多个桌面 它需要一个第三方 DLL 文件 一个 C 库 lpsolve55 dll 对于那些感兴趣的人 它是一个免费的 MIP LP 求解器 请参阅 lpsol
  • 尽管浮点数相同,但它们并不相等? [复制]

    这个问题在这里已经有答案了 下面的程序输出This No is not same 当两个数字相同时为什么会这样做 void main float f 2 7 if f 2 7 printf This No is same else prin
  • 如何在 ASP.NET Core 6.0 Web API 项目中启用 cors?

    在我的 ASP NET Core 6 0 Web API 项目中配置了 CORS 但预检请求收到 http 405 错误 换句话说 不允许使用 HTTP OPTION 看起来 cors 没有启用 我见过的例子config EnableCor
  • C语言中没有循环可以打印数组吗?

    例如 在Python中 如果我们将一个列表作为数组 它会直接用一行代码打印整个数组 有什么办法可以用C语言实现同样的事情吗 简短回答 No 对表格上几乎所有问题的简短回答 用 C 语言做 X 工作能像用 Python 一样简单吗 No 长答
  • 应用新设置时如何防止 GraphicsDevice 被丢弃?

    我的游戏窗口允许手动调整大小 这意味着它可以像任何其他普通窗口一样通过拖动其边缘来调整大小 游戏还利用了RenderTarget2D rt2d 在主 Draw 方法中设置主渲染目标 GraphicsDevice SetRenderTarge
  • 多线程 - 比单线程慢

    当我使用多个线程而不是单线程运行程序时 它会变慢 不是应该更快吗 该程序应该遍历从起始目录开始的所有目录 并查找并打印所有名为 X 的文件 代码如下 while done pthread mutex lock lock if list is
  • 重定向 std::cout

    我需要一个类 在其对象的生命周期内将一个 ostream 重定向到另一个 ostream 经过一番修补后 我想出了这个 include
  • 如果我重新分配并且新大小为 0,会发生什么情况。这与释放等效吗?

    给出以下代码 int a NULL a calloc 1 sizeof a printf d n a a realloc a 0 printf d n a return 0 它返回 4078904 0 这个 realloc 相当于 free
  • 何时分离或加入 boost 线程?

    我有一个方法 大约每 30 秒触发一次 我需要在一个线程中包含它 我有一个可以从类外调用的方法 像 call Threaded Method 这样的东西会创建一个线程 该线程本身会调用最终的线程方法 这些是 MyClass 的方法 void
  • 如何使用 C# 将表格粘贴到 Ms-Word 文档的末尾

    我有一个预制的 Word 模板 其中有一个表格 我想打开它 然后在文档末尾添加 粘贴 另一个表格 问题是它不会转到文档的末尾 而是将新表格粘贴到原始表格的第一个单元格中 任何帮助将不胜感激 previous code copied a ta
  • 文本框中“结束编辑”的事件

    我正在 winform c 中使用文本框 并使用文本在数据库中进行查询 但每次文本更改时 我都需要不断查阅文本框的文本 因此 对于这些 我使用 KeyUp 但这个活动太慢了 文本框编辑完成后是否会触发任何事件 我考虑完成2个条件 控制失去焦
  • 如何阻止 Control-I 在 CoreWindow 范围内的 UWP 文本框中插入选项卡?

    当我在 UWP 应用程序中有一个 TextBox 时 对我来说 奇怪的行为 在 Windows 10 中创建通用的空白应用程序 UWP 应用程序 使用以下代码将文本框添加到默认网格
  • 在 C# 窗口应用程序中运行 C/C++ 控制台应用程序?

    现在 我想开发一个简单的应用程序 因此我决定最快的编码方式是 C NET 但现在 我很难实现我需要的功能之一 我想做的是在 C 应用程序的窗口内运行 C C 控制台应用程序 就像在虚幻前端中一样 添加一点通信方式 以便我可以为控制台应用程序
  • C# 模式匹配

    我对 C 有点陌生 我正在寻找一个字符串匹配模式来执行以下操作 我有一个像这样的字符串 该书将在 唐宁街 11 号接待处 并将由主要医疗保健人员参加 我需要创建一个 span 标签来使用 startIndex 和 length 突出显示一些
  • 是否可以检测流是否已被客户端关闭?

    简要介绍一下情况 我有一项服务可以通过套接字接收信息并发送回复 连接不安全 我想设置另一个可以为这些连接提供 TLS 的服务 这个新服务将提供单个端口并根据提供的客户端证书分发连接 我不想使用 stunnel 有几个原因 其中之一是每个接收

随机推荐

  • 【云原生】Docker 详解(三):Docker 镜像管理基础

    Docker 详解 三 Docker 镜像管理基础 1 镜像的概念 镜像可以理解为应用程序的集装箱 而 Docker 用来装卸集装箱 Docker 镜像含有启动容器所需要的文件系统及其内容 因此 其用于创建并启动容器 Docker 镜像采用
  • 数据结构算法—邻接表存储的无向图求连通分量个数

    数据结构算法 邻接表存储的无向图求连通分量个数 邻接表存储结构 typedef struct ArcNode int adjvex 边指向的顶点 struct ArcNode nextarc 下一条边的指针 ArcNode typedef
  • 感谢我的python老师

    Python自动化开发 金角大王版 http www cnblogs com alex3714 articles 5885096 html 转载于 https www cnblogs com tianqizhi p 8385650 html
  • canvas 流程图bug

    问题一 在当前年份点击选择没有取消调选择在去选择年份是会出bug 修改 canvas 添加点击事件后状态恢复到初始值 修改完 效果图
  • Swagger--基础--02--集成Springboot

    Swagger 基础 02 集成Springboot 代码位置 https gitee com DanShenGuiZu learnDemo tree master swagger learn 1 代码结构 2 代码 User packag
  • vue中一个项目里兼容移动端和pc端

    话不多说 上代码 先来看一下我的文件 路由文件 index js import Vue from vue import Router from vue router Vue use Router export default new Rou
  • 【实践经验】PPT导出SVG格式通过Inkscape转化为pdf

    目录 背景 方案调研 Inkspace 配置 将svg转为pdf 背景 在写论文过程中不可避免需要作图 常用的工具就是PPT 但是在导出图片的过程中通常会遇到一个问题 图片导出为png格式不够清晰 放大后比较模糊影响观感 那么有没有解决方案
  • AcWing4118. 狗和猫

    输入样例1 3 6 10 4 0 CCDCDD 4 1 2 0 CCCC 4 2 1 0 DCCD 输出样例1 Case 1 YES Case 2 YES Case 3 NO 样例1解释 在 Case 1 中 一共有 1010 份狗粮和 4
  • VTK环境安装教程

    安装前依赖环境 CMake VS2019 VTK压缩包 8 2 0即可 build过程 第一次分析完 找到下图中选中项 勾选Configure 解释勾选项 BUILD EXAMPLES 生成一些vtk官方的examples 帮助理解学习 当
  • SQL 后计算的利器 SPL

    目录 专业的结构化数据对象 强大的结构化数据计算能力 灵活的流程控制能力 优化体系结构 SPL资料 现代应用开发中 通常只用SQL实现简单的数据存取动作 而主要的计算过程和业务逻辑直接在应用程序中实现 主要原因在于 过于复杂的SQL很难调试
  • Python JS逆向篇(四)

    Python JS逆向篇 四 找到参数加密位置 跟进window asrsea函数 结果 扣取的js代码 扩展 逆向主题 某易云评论数据 请求时的加密参数 注 文章所涉及内容只做学习参考交流 不做除此之外的任何其它用途 找到参数加密位置 我
  • 解析XML文件时的嵌套异常SAXParseException

    解析XML文件时的嵌套异常SAXParseException 引言 XML 可扩展标记语言 是一种常用的数据格式 用于存储和传输结构化数据 在开发过程中 我们经常需要解析XML文件来获取其中的数据 然而 XML解析过程中可能会遇到各种异常情
  • 关于利用Qt编写应用程序的帮助文档

    转载请注明出处 关于利用Qt编写应用程序的帮助文档 首先推荐Qt官网的example 官网的例子讲的很细致很全面 不过官网的例子全是英文的 百度文库里有对这个例子的翻译 我也看了一下 感觉还不如去看英文的 好的言归正传 讲一下大概的步骤 1
  • node快速创建一个工程项目

    1 安装express npm install g express 2 新建一个工程 指定使用ejs模板引擎 express e 文件名 3 安装需要的模块 cd 文件名 npm install 4 启动 SET DEBUG 文件名 npm
  • Oracle学习(14)【DBA向】:利用DBCA创建Oracle数据库

    数据库管理任务 DBA 1 评测数据库服务器硬件 2 安装Oracle数据库软件 3 规划数据库 4 创建并且打开数据库 5 数据库备份 6 注册用户 7 实现数据库计划 8 全库备份 9 调整数据库性能 数据库规划 作为一名DBA 你必须
  • mac m1 安装 protobuf

    mac m1各种踩坑中 一 背景 mac m1 机器上使用golang grpc 二 安装流程 1 安装protobuf 注 已经安装了brew brew install protobuf 2 安装go的支持 go install goog
  • 用 Python 打造 AIGC 的「操作系统」

    carefree0910 carefree drawboard Infinite Drawboard in Python github com https github com carefree0910 carefree drawboard
  • 挖金矿问题(c++求解)

    n个金矿 共有w个工人 目前可以用的人数 F收益 F n w 递推函数 n个金矿 共有w个工人 目前可以用的人数 F收益 F n w 那么该问题的边界值如下 当w 0且w
  • 蓝桥杯 2019年号字串

    题目 试题 B 年号字串 问题描述 小明用字母 A 对应数字 1 B 对应 2 以此类推 用 Z 对应 26 对于 27以上的数字 小明用两位或更长位的字符串来对应 例如 AA 对应 27 AB 对应 28 AZ 对应 52 LQ 对应 3
  • C# 细说async/await的用法

    目录 一 引言 二 实例演示 2 1 多线程同步执行下载任务 任务完成后通知 2 2 异步执行下载任务 任务完成后通知 三 async await的用法 3 1 跨线程修改UI控件 3 2 异步获取数据 一 引言 首先先来区分一下 同步方法