【.NET Core】深入理解异步编程模型(APM)

【.NET Core】深入理解异步编程模型(APM)

文章目录

  • 【.NET Core】深入理解异步编程模型(APM)
    • 一、APM概述
    • 二、IAsyncResult接口
      • 2.1 BeginInvoke
      • 2.2 EndInvoke
      • 2.3 IAsyncResult属性
      • 2.4 IAsyncResult异步演示
    • 三、通过结束异步操作来阻止应用程序执行
    • 四、使用AsyncWaitHandle阻止应用程序的执行
    • 五、轮询异步操作的状态
    • 六、总结

在这里插入图片描述

一、APM概述

APM英文是Asynchronous Programming Model是net 1.0时期就提出的一种异步模式,并基于IAsyncResult接口实现Beginxxx和Endxxx的两个方法来实现的,Beginxxx方法是开始异步操作,Endxxx方法是结束异步操作。

在调用Beginxxx后,应用程序可以继续在调用线程上执行指令,同时异步操作在另一个线程上执行。每次调用Beginxxx时,应用程序还应调用Endxxx来获取操作的结果。

public class Budget
{public delegate string FindBudgetDelegate();public string FindBudget() {Thread.Sleep(20000);return $"2024年财年预算-预算科目编制.";}
}

IAsyncResult实现APM

static void Main(string[] args)
{Budget budget =new Budget();Budget.FindBudgetDelegate findBudgetDelegate  =budget.FindBudget;IAsyncResult asyncResult =   findBudgetDelegate.BeginInvoke(null,null);string response =  findBudgetDelegate.EndInvoke(asyncResult);Console.WriteLine(response);
}

二、IAsyncResult接口

接口IAsyncResult由包含可异步操作的方法的类实现。它是启动操作的方法的返回类型。IAsyncResult当异步操作完成时,对象会传递给委托调用AsyncCallback的方法。使用.NET可以以异步方法调用任何方法。首先,需要定义一个委托,该委托具有与调用的方法相同的签名。公共语言运行时将自动用适当的签名为此委托定义BeginInvokeEndInvoke方法。

2.1 BeginInvoke

BeginInvoke方法启动异步调用。该方法具有与你要异步的方法相同的参数,另加两个可选参数。第一个参数是一个AsyncCallBack委托。此委托引用在异步调用完成时要调用的方法。第二个参数是一个用户定义的对象,该对象将信息传递到回调方法。BeginInvoke将立即返回,而不会等待异步调用完成。BeginInvoke返回可用于监视异步调用的进度的IAsyncResult

2.2 EndInvoke

EndInvoke方法用于检索异步调用的结果。它可以在调用BeginInvoke之后的任意时间调用。如果异步调用尚未结束,那么EndInvoke将阻止调用线程,直到完成异步调用。EndInvoke的参数包括要异步执行的方法的outref参数。

2.3 IAsyncResult属性

序号属性说明
1AsyncState获取一个用户定义的对象,该对象限定或包含有关异步操作的信息
2AsyncWaitHandle获取用于等待异步操作完成的WaitHandle
3CompletedSynchronously获取一个值,该值指示异步操作是否同步完成
4IsCompleted获取一个值,该值指示异步操作是否完成

2.4 IAsyncResult异步演示

static void Main(string[] args)
{Budget budget =new Budget();Budget.FindBudgetDelegate findBudgetDelegate  =budget.FindBudget;IAsyncResult asyncResult =   findBudgetDelegate.BeginInvoke(new AsyncCallback(FindOneAsyncCallBack),null);Console.WriteLine("BeginInvoke异步开始");Console.WriteLine($"当前主线程{Thread.CurrentThread.Name}");Console.WriteLine($"Main->{asyncResult.AsyncState}");Console.WriteLine("WaitOne");Console.ReadKey();
}static void FindOneAsyncCallBack(IAsyncResult asyncResult) 
{Budget.FindBudgetDelegate budgetDelegate =   ((AsyncResult)asyncResult).AsyncDelegate as Budget.FindBudgetDelegate;Console.WriteLine(budgetDelegate.EndInvoke(asyncResult));Console.WriteLine($"FindOneAsyncCallBack->{asyncResult.AsyncState}");
}

三、通过结束异步操作来阻止应用程序执行

如果应用无法在等待异步操作结果期间继续执行其他工作,必须阻止应用一直到操作完成。可以使用下列方法之一,在应用等待异步操作完成期间阻止应用的主程序:

  • 调用异步操作的EndOperationName方法。
  • 使用异步操作的BeginOperationName方法返回的IAsyncResultAsyncWaitHandle属性。

在异步操作完成前使用EndOperationName方法阻止的应用程序,通常会调用BeginOperationName方法,执行任何不需要等待操作结果也可以执行的工作,然后调用EndOperationName

static void Main(string[] args)
{Budget budget =new Budget();Budget.FindBudgetDelegate findBudgetDelegate  =budget.FindBudget;IAsyncResult asyncResult =   findBudgetDelegate.BeginInvoke(null,null);string response =  findBudgetDelegate.EndInvoke(asyncResult);Console.WriteLine(response);
}

四、使用AsyncWaitHandle阻止应用程序的执行

在异步操作完成前使用一个或多个WaitHandle对象阻止的应用,通常会调用BeginOperationName方法,执行任何不需要等待操作结果也可以执行的工作,并在一个或多个异常操作完成前一直处于阻止状态。可以使用AsyncWaitHandle调用WaitOne方法之一,对单一操作阻止应用。若要在等待一组异步操作完成期间阻止应用,请将关联的AsyncWaitHandle对象存储到数组中,并调用WaitAll方法之一。若要在等待一组异步操作中任一操作完成期间阻止应用。请将关联的AsyncWaitHandle对象存储到数组中,并调用WaitAny方法之一。

static void Main(string[] args)
{Budget budget =new Budget();Budget.FindBudgetDelegate findBudgetDelegate  =budget.FindBudget;IAsyncResult asyncResult =   findBudgetDelegate.BeginInvoke(null,null);// Wait until the operation completesasyncResult.AsyncWaitHandle.WaitOne();string response =  findBudgetDelegate.EndInvoke(asyncResult);Console.WriteLine(response);
}

五、轮询异步操作的状态

如果应用可以在等待异步操作结果期间继续执行其他工作,不得阻止应用一直到操作完成。请使用下列方法之一,在应用等待异步操作完成期间继续执行指令:

  • 使用返回IAsyncResultIsCompleted属性,确定操作是否已完成。这种方法称为"轮询"。
  • 使用AsyncCallBack委托,在单独的线程中处理异步操作结果。

六、总结

使用委托可通过异步方式调用同步方法。 如果同步调用委托,Invoke 方法将在当前线程上直接调用目标方法。 如果调用 BeginInvoke 方法,公共语言运行时 (CLR) 将对请求进行排队并立即返回给调用方。 目标方法将在线程池中的某个线程上异步调用。 提交请求的原始线程可以不受限制地继续与目标方法并行执行。 如果已在对 BeginInvoke 方法的调用中指定回叫方法,则目标方法结束时,将调用回叫方法。 在回叫方法中,EndInvoke 方法将获取返回值和所有输入/输出或仅输出参数。 如果调用 BeginInvoke 时未指定回叫方法,则可能从调用 BeginInvoke 的线程上调用 EndInvoke

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

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

相关文章

C#有一张表 怎么获取某一列下面的含有数据的单元格datatable

C#我有一张表,怎么获取某一列下面的含有数据的单元格加入数组里面 SqlHelper sql new SqlHelper(); DataTable dt sql.GetTableFromStoredProcedure(); // 调用获取表格的方法 // 使用 LINQ 查询…

系统架构演变

1.1系统架构的演变 2008年以后,国内互联网行业飞速发展,我们对软件系统的需求已经不再是过去”能用就行”这种很low的档次了,像抢红包、双十一这样的活动不断逼迫我们去突破软件系统的性能上限,传统的IT企业”能用就行”的开发思…

感染了后缀为.BecSec-P-XXXXXXXX勒索病毒如何应对?数据能够恢复吗?

导言: 随着科技的不断发展,网络安全威胁也不断演变,其中BecSec-P-XXXXXXXX勒索病毒是一种引起关注的威胁。该病毒通过加密用户的数据文件,要求受害者支付赎金以获取解密密钥。在本文中,我们将深入介绍BecSec-P-XXXXXX…

yum下载源,vim使用

文章目录 yum本地配置lzrsz命令行互传scp(远程拷贝)vim yum本地配置 [rootiZf8z3j2ckkap6ypn717msZ ~]# pwd /root [rootiZf8z3j2ckkap6ypn717msZ ~]# ls /etc/yum.repos.d CentOS-Base.repo epel.repo //本地配置源yum会根据/etc/yum.repo.d路径下的配置文件来构成自己的下载…

人类行为动作数据集大合集

最近收集了一大波关于人类行为动作的数据集,主要包括:动作识别、行为识别、活动预测、动作行为分类等数据集。废话不多说,接下来就给大家介绍这些数据集!! 1、用于自动视频编辑的视频Blooper数据集 用于自动视频编辑…

idea中debug Go程序报错error layer=debugger could not patch runtime.mallogc

一、问题场景 在idea中配置了Go编程环境,可以运行Go程序,但是无法debug,报错error layerdebugger could not patch runtime.mallogc: no type entry found, use ‘types’ for a list of valid types 二、解决方案 这是由于idea中使用的d…

SpringBoot统一返回和统一异常处理

Session 认证和 Token 认证 过滤器和拦截器 SpringBoot统一返回和统一异常处理 上篇文章我们学习了基于 Token 认证的登录功能实现,分别使用了过滤器和拦截器去实现登录功能,这篇文章我们来学习项目中常用的统一返回结果和统一异常处理。 一、统一返…

【LeetCode每日一题】670. 最大交换

2024-1-22 文章目录 [670. 最大交换](https://leetcode.cn/problems/maximum-swap/)思路: 670. 最大交换 思路: 从后往前遍历整数的字符数组,找到第一个比当前最大值小的数字,然后将该数字与最大值进行交换。 将给定的整数转换为…

数据库-分库分表初探

文章目录 分库策略垂直切分垂直分库(专库专用)垂直分表(拆表)优点缺点 水平(Sharding)切分水平分表库内分表分库分表优点缺点 分表策略hash取模方案range范围区间取值方案映射表方案 分库分表问题事务一致性问题跨节点关联查询跨节…

机器学习-PCA降维【手撕】

降维算法 降维算法中的”降维“,指的是降低特征矩阵中特征的数量,其目的是为了让算法运算更快,效果更好,同时可以方便数据可视化。过高的维度特征维度的特征矩阵无法通过可视化,数据的性质也就比较难理解。其中主要用…

浅谈拨测在网络安全中的应用

在当今数字化时代,网络安全成为各个行业和组织关注的焦点。为了保障网络的稳定性和信息的安全,拨测安全性成为一种日益重要的工具。本文将介绍拨测在网络安全中的应用: 1.威胁模拟 通过威胁模拟,拨测安全性可以模拟各种网络攻击&a…

初谈C++:命名空间、输入输出

文章目录 前言C关键字命名空间命名空间的作用命名空间定义命名空间的使用 C的输入&输出 前言 什么是C? C语言是结构化和模块化的语言,适合处理较小规模的程序。对于复杂的问题,规模较大的程序,需要高度的抽象和建模时&#…

mockjs(3)

mockjs(1) mockjs(2) 这篇主要是Mock.random工具类,前段要用的话主要是在模版中的占位符。mockjs(1)里面的3.2 6 Mock.random Mock.Random 是一个工具类,用于生成各种随机数据。 …

数据结构与算法-绪论

1 绪论 程序 数据结构 算法数据的逻辑结构 四种: 线性结构树形结构图状结构集合结构 数据的存储结构 (逻辑结构在存储器中的映像)常见的有: 数组链表栈队列树堆散列表图 基本数据类型: intfloatdoublecharbool 算法…

Wpf 使用 Prism 实战开发Day15

用户登录和注册接口 一.创建用户登录注册控制器&#xff08;LoginController&#xff09; /// <summary>/// 用户登录注册控制器/// </summary>[ApiController][Route("api/[controller]/[action]")]public class LoginController: ControllerBase{} 二.…

houdini fft 使用三层for each结构 以及for 问题

for each 中 使用 attrib wrangle detail时&#xff0c;不连接foreach_count1&#xff0c;只运行一次 for each 问题 merge eachiteration 对结构进行合并 transform 位置的移动针对的是原位置对原点的距离&#xff0c;而非移动后置0后再移

vivado I/O和时钟规划是定义和分析、I/O和时钟规划阶段、RTL前I/O规划、RTL I/O规划、网表I/O规划、实施设计的最终I/O验证

介绍 I/O和时钟规划是定义和分析 FPGA/自适应SoC和印刷电路板&#xff08;PCB&#xff09;&#xff0c;并分配各种互连信号到设备的物理引脚。这个过程包括PCB设计者、FPGA设计者和系统设计者有以下关注点和要求&#xff1a; •简化关键信号连接&#xff0c;以缩短信号长度并…

Hotspot源码解析-第22章-vtable和itable的重新初始化

第22章-vtable和itable的重新初始化 这个函数的调用流程是 init.cpp->init_globals() universe.cpp->universe_post_init() bool universe_post_init() {// 防止二次初始化assert(!is_init_completed(), "Error: initialization not yet completed!");Univ…

【C++】list容器功能模拟实现

介绍 上一次介绍了list队容器的迭代器模拟&#xff0c;这次模拟实现list的简单功能&#xff0c;尤其要注意构造函数、析构函数、以及赋值运算符重载的实现。 list容器需要接纳所有类型的数据&#xff0c;因此&#xff0c;结构设置与迭代器设置同理&#xff0c;需要引入结点&…

Python中的open与JSON的使用

目录 1 使用 open 函数进行文件操作 2 使用 json 模块进行 JSON 数据处理&#xff1a; 2.1 写入JSON 文件 2.2 读取JSON 文件 在 Python 中&#xff0c;open 函数和 json 模块常用于文件的读写和 JSON 数据的处理。 1 使用 open 函数进行文件操作 open 函数用于打开文件…