C# 异步编程场景

news2024/9/20 0:00:42

前言

异步编程允许程序在等待某些操作(如文件读写、网络请求等)完成时,不必阻塞主线程,从而可以继续执行其他任务。这种非阻塞的特性对于提高应用程序的并发性和响应速度至关重要。C# 通过 asyncawait 关键字,以及 Task 类,为异步编程提供了简洁而强大的支持。

本文将深入探讨 C# 中的异步编程场景,包括其基本概念、工作原理以及如何在实际开发中应用异步编程技术。我们将通过实例演示如何利用 C# 的异步特性来编写高效、响应迅速的应用程序,同时也会讨论在异步编程中可能遇到的一些常见问题及其解决方案。

如果需要 I/O 绑定(例如从网络请求数据、访问数据库或读取和写入到文件系统),则需要利用异步编程。 还可以使用 CPU 绑定代码(例如执行成本高昂的计算),对编写异步代码而言,这是一个不错的方案。

C# 拥有语言级别的异步编程模型,让你能轻松编写异步代码,而无需应付回调或受限于支持异步的库。 它遵循基于任务的异步模式 (TAP)。

异步模型概述

异步编程的核心是 Task 和 Task<T> 对象,这两个对象对异步操作建模。 它们受关键字 async 和 await 的支持。 在大多数情况下模型十分简单:

  • 对于 I/O 绑定代码,等待一个在 async 方法中返回 Task 或 Task<T> 的操作。
  • 对于 CPU 绑定代码,等待一个使用 Task.Run 方法在后台线程启动的操作。

await 关键字有这奇妙的作用。 它控制执行 await 的方法的调用方,且它最终允许 UI 具有响应性或服务具有灵活性。 虽然有方法可处理 async 和 await 以外的异步代码,但本文重点介绍语言级构造。

 备注

在以下一些示例中,System.Net.Http.HttpClient 类用于从 Web 服务下载某些数据。 这些示例中使用的 s_httpClient 对象是 Program 类的静态字段(请检查完整示例):

private static readonly HttpClient s_httpClient = new();

I/O 绑定示例:从 Web 服务下载数据

你可能需要在按下按钮时从 Web 服务下载某些数据,但不希望阻止 UI 线程。 可执行如下操作来实现:

C#复制

s_downloadButton.Clicked += async (o, e) =>
{
    // This line will yield control to the UI as the request
    // from the web service is happening.
    //
    // The UI thread is now free to perform other work.
    var stringData = await s_httpClient.GetStringAsync(URL);
    DoSomethingWithData(stringData);
};

代码表示目的(异步下载数据),而不会在与 Task 对象的交互中停滞。

CPU 绑定示例:为游戏执行计算

假设你正在编写一个移动游戏,在该游戏中,按下某个按钮将会对屏幕中的许多敌人造成伤害。 执行伤害计算的开销可能极大,而且在 UI 线程中执行计算有可能使游戏在计算执行过程中暂停!

此问题的最佳解决方法是启动一个后台线程,它使用 Task.Run 执行工作,并使用 await 等待其结果。 这可确保在执行工作时 UI 能流畅运行。

static DamageResult CalculateDamageDone()
{
    return new DamageResult()
    {
        // Code omitted:
        //
        // Does an expensive calculation and returns
        // the result of that calculation.
    };
}

s_calculateButton.Clicked += async (o, e) =>
{
    // This line will yield control to the UI while CalculateDamageDone()
    // performs its work. The UI thread is free to perform other work.
    var damageResult = await Task.Run(() => CalculateDamageDone());
    DisplayDamage(damageResult);
};

此代码清楚地表达了按钮的单击事件的目的,它无需手动管理后台线程,而是通过非阻止性的方式来实现。

内部原理

在 C# 方面,编译器将代码转换为状态机,它将跟踪类似以下内容:到达 await 时暂停执行以及后台作业完成时继续执行。

从理论上讲,这是异步的承诺模型的实现。

需了解的要点

  • 异步代码可用于 I/O 绑定和 CPU 绑定代码,但在每个方案中有所不同。
  • 异步代码使用 Task<T> 和 Task,它们是对后台所完成的工作进行建模的结构。
  • async 关键字将方法转换为异步方法,这使你能在其正文中使用 await 关键字。
  • 应用 await 关键字后,它将挂起调用方法,并将控制权返还给调用方,直到等待的任务完成。
  • 仅允许在异步方法中使用 await

识别 CPU 绑定和 I/O 绑定工作

本指南的前两个示例演示如何将 async 和 await 用于 I/O 绑定和 CPU 绑定工作。 确定所需执行的操作是 I/O 绑定或 CPU 绑定是关键,因为这会极大影响代码性能,并可能导致某些构造的误用。

以下是编写代码前应考虑的两个问题:

1、代码是否会“等待”某些内容,例如数据库中的数据?

如果答案为“是”,则你的工作是 I/O 绑定

2、代码是否要执行开销巨大的计算?

如果答案为“是”,则你的工作是 CPU 绑定

如果你的工作为 I/O 绑定,请使用 async 和 await(而不使用 Task.Run)。 不应使用任务并行库。

如果你的工作属于 CPU 绑定,并且你重视响应能力,请使用 async 和 await,但在另一个线程上使用 Task.Run 生成工作。 如果该工作同时适用于并发和并行,还应考虑使用任务并行库。

此外,应始终对代码的执行进行测量。 例如,你可能会遇到这样的情况:多线程处理时,上下文切换的开销高于 CPU 绑定工作的开销。 每种选择都有折衷,应根据自身情况选择正确的折衷方案。

最后

如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。也可以加入微信公众号 [DotNet技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长!优秀是一种习惯,欢迎大家留言学习!

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

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

相关文章

hh exe所选的程序不能与此文件类型相关联。请选择其他程序。

按照hh exe打开chm文件显示所选的程序不能与此文件类型相关联。请选择其他程序。 以上错误来自于 cmd命令行 cd C:\Windows\hh.exe 要打开的chm文件报错 其实根本原因是在设置中.chm文件默认打开方法被其他软件占用了&#xff0c;解决办法只能删除那个软件&#xff0c;如果是W…

828华为云征文 | 云服务器Flexus X实例:部署 AgentOps,全方位监测智能体

目录 一、什么是 AgentOps ? 二、部署 AgentOps 2.1 安装 AgentOps 2.2 注册账号 2.3 生成 API_KEY 三、AgentOps 实例 3.1 创建实例 3.2 运行实例 四、总结 通过深入体验华为云的 Flexus云服务器X实例&#xff0c;我发现它不仅提供了直接通过公网访问的便利性&#…

【 html+css 绚丽Loading 】 000049 流云穿梭环

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f…

回归预测|基于遗传优化卷积神经网络的数据回归预测Matlab程序GA-CNN 多特征输入单输出 附赠基础CNN

回归预测|基于遗传优化卷积神经网络的数据回归预测Matlab程序GA-CNN 多特征输入单输出 附赠基础CNN 文章目录 一、基本原理1. 卷积神经网络&#xff08;CNN&#xff09;2. 遗传算法&#xff08;GA&#xff09;3. GA-CNN回归预测模型总结 二、实验结果三、核心代码四、代码获取五…

智能BI项目第一期

该项目是全程跟着鱼皮,还未进行功能扩展。为了方便日后复习,打算将一些重要的步骤记录下来。 项目概述 BI:即商业智能:Business Intelligence 过去 需要手动导入数据、选择要分析的字段和图表&#xff0c;并由专业的数据分析师完成分析&#xff0c;最后得出结论。 现在 用户…

docker发布redis容器

1.导入redis镜像 2.写docker-compose文件 并创建容器 redis:container_name: redisimage: redis:latestports:- "6379:6379"restart: always 3.测试一下

“深入解析:MySQL半同步复制的配置指南与实践技巧“

本次配置是在已搭建好主从复制的架构中进行配置 配置环境 操作系统 master节点 slave节点 centos7 8.0.37 8.0.37 配置半同步复制 配置master 安装master半同步复制插件 INSTALL PLUGIN rpl_semi_sync_source SONAME semisync_source.so; 在MySQL的配置文件中添加配置…

论文(六):Fire-Net: A Deep Learning Framework for Active Forest Fire Detection

文章目录 1.Introduction2.Study Area2.1Landsat-8 Dataset2.2Inventory data 3.Methodology3.1Image Pre-processing3.2Proposed Deep Learning Architecture (Fire-Net)3.2.1Convolution Layers3.2.2 Evaluation Indices/methods or accuracy assessment. 4.Results4.1 Austr…

JVM HotSpot 虚拟机: 对象的创建, 内存布局和访问定位

目录 前言 对象的创建 对象的内存布局 对象的访问定位 前言 了解JVM的内存区域划分之后, 也大致了解了java程序的内存分布模型, 也了解它里面的内存区域里面的类型和各个类型的作用, 接下来我们进一步从对象创建到访问的角度, 来看看这些内存区域之间是怎么关联起来的. …

【C++篇】C++类与对象深度解析(二):类的默认成员函数详解

文章目录 【C篇】C类与对象深度解析&#xff08;二&#xff09;前言1. 类的默认成员函数2. 构造函数2.1 函数名与类名相同2.2 无返回值2.3 对象实例化时系统会自动调用2.4 构造函数可以重载2.5 默认构造函数的生成规则2.6 无参构造函数与全缺省构造函数的关系2.7 内置类型与自定…

五、(JS)window中的定时器

一、为什么叫做window中的定时器 我们在全局中会用到一些函数&#xff0c;比如说alert函数&#xff0c;prompt函数&#xff0c;setTimeout等等 我们有在这里定义过这些函数吗&#xff1f;很明显没有。可见我们这些函数都是来自于window。 所以还可以写成window.setTimeout。…

Linux 开发工具(vim、gcc/g++、make/Makefile)+【小程序:进度条】-- 详解

目录 一、Linux软件包管理器 - yum&#xff08;ubuntu用apt代替yum&#xff09;1、Linux下安装软件的方式2、认识 yum3、查找软件包4、安装软件5、如何实现本地机器和云服务器之间的文件互传 二、Linux编辑器 - vim1、vim 的基本概念2、vim 下各模式的切换3、vim 命令模式各命令…

【Linux篇】TCP/IP协议(笔记)

目录 一、TCP/IP协议族体系结构 1. 数据链路层 &#xff08;1&#xff09;介绍 &#xff08;2&#xff09;常用协议 ① ARP协议&#xff08;Address Resolve Protocol&#xff0c;地址解析协议&#xff09; ② RARP协议&#xff08;Reverse Address Resolve Protocol&…

[Meachines] [Easy] Sauna DC域+AS-REP+TGT票证窃取+AutoLogon凭据+DCSync攻击

信息收集 IP AddressOpening Ports10.10.10.175TCP:53,80,88,135,139,389,445,464,593,3268,3269,5985 $ nmap -p- 10.10.10.175 --min-rate 1000 -sC -sV PORT STATE SERVICE VERSION 53/tcp open domain? | fingerprint-strings: | DNSVersionBindReqTCP…

电容的不同材质对应的温度范围

电容的温度范围是指电容在不同温度下能够正常工作的范围。不同材质的电容具有不同的温度特性&#xff0c;以下是一些常见电容材质的温度范围。 C0G/NP0&#xff1a;这类电容具有非常稳定的电气性能&#xff0c;工作温度范围通常为-55℃至125℃。 X7R&#xff1a;X7R材质的电容…

2021高教社杯全国大学生数学建模竞赛C题 Python代码演示

目录 问题一1.1 根据附件 1&#xff0c;对 402 家供应商的供货特征进行量化分析计算供货特征数据标准化对正向指标归一化对负向指标归一化 1.2 建立反映保障企业生产重要性的数学模型熵权法熵权法-TOPSISAHP 1.3 在此基础上确定 50 家最重要的供应商&#xff0c;并在论文中列表…

软件工程毕业设计开题汇总

文章目录 &#x1f6a9; 1 前言1.1 选题注意事项1.1.1 难度怎么把控&#xff1f;1.1.2 题目名称怎么取&#xff1f; 1.2 开题选题推荐1.2.1 起因1.2.2 核心- 如何避坑(重中之重)1.2.3 怎么办呢&#xff1f; &#x1f6a9;2 选题概览&#x1f6a9; 3 项目概览题目1 : 大数据电商…

几个常见的非初等函数

在多个激励共同作用下,其响应恒等于每个激励单独引起的响应之和。这种现象称为线性现象。线性性质使得对这类现象的数学描述大为简化,它是线性系统理论的基础。 本篇博客将简单介绍以下几个常用的非初等函数。 rect 矩形函数(Rectangular Function)sinc 函数(Sinc Function)三…

“树”据结构:并查集从入门到AC

“树”据结构&#xff1a;并查集 前言算法设计代码示例优化相关文章 前言 在一组数据中&#xff0c;数据被分为了不同的集合&#xff0c;那么其中的集合往往可以用树形来表示。而区分集合&#xff0c;与查找集合的元素&#xff0c;就会成为核心的问题。并查集主要就是解决这类…