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

news2024/11/25 4:34:52

【.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 completes
    asyncResult.AsyncWaitHandle.WaitOne();
    string response =  findBudgetDelegate.EndInvoke(asyncResult);
    Console.WriteLine(response);
}

五、轮询异步操作的状态

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

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

六、总结

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

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

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

相关文章

【Linux】yum本地配置

配置将来是在干什么? yum会根据/etc/yum.repos.d/该路径下面的配置文件,来构成自己的下载路径,(根据OS版本,根据你要下载的软件),yum帮助我们下载,安装 一般的机器,内置…

Operation

contents 服务器一、相关概念1.1 云服务器与实例1.2 关于域名解析延时与80端口1.3 关于备案1.4 关于SSL证书1.5 关于SSL证书的签发1.6 关于SSL证书的部署1.7 关于LNMP和LAMP1.8 关于bt面板 二、单服务器单一级域名多网站2.1 创建多个二级域名2.2 解析二级域名绑定到服务器上2.3…

【QML COOK】- 011-动画插值设置

QML中内置了一些动画插值类型。不同的插值类型可以通过Animation的easing属性设置。具体可见:PropertyAnimation QML Type | Qt Quick 6.6.1 1. 创建工程在Main.qml,中编写如下代码 import QtQuickWindow {width: 1000height: 100visible: truetitle: …

数字人直播系统跟无人直播系统的区别是什么?如何选择呢?

有媒体预测,未来几年,数字人工智能将呈现爆发式的增长,数字人系统将广泛应用于各个行业,比如数字人直播,数字人短视频播报,数字人制作的海报宣传等等,当然,这其中应用最广的当属数字…

Python实现离散选择Logit模型(Logit算法)项目实战

说明:这是一个机器学习实战项目(附带数据代码文档视频讲解),如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 Logit模型(Logit model,也译作“评定模型”,“分类评定模型”&…

从想象到现实:Midjourney的AI图像生成之旅

从想象到现实:Midjourney的AI图像生成之旅 继ChatGPT之后,Midjourney作为AI艺术的璀璨明珠,吸引了全球范围内的广泛关注。这款工具通过先进的AI技术,将用户输入的文字描述转化为精美绝伦的图像。无论是风景画、肖像画还是抽象艺术…

CentOS7的安装配置

一. CentOS7的安装【在虚拟机中】 首先创建一个虚拟机, 这个没什么好说的,基本上都是下一下一步安装。 注意它的存放位置最好不要放在C盘, 以及开始创建时选择”稍后安装操作系统“ 创建完成后再配置镜像文件 开启虚拟机,继续下…

【K8S】Kubernetes 中滚动发布由浅入深实战

目录 一、Kubernetes中滚动发布的需求背景1.1 滚动发布1.2 滚动发布、蓝绿发布、金丝雀发布的区别 二、Kubernetes中实现滚动发布2.1 定义Kubernetes中的版本2.2 创建 Deployment 资源对象2.2.1 在 Yaml 中定义 Deployment 资源对象2.2.2 执行命令创建 Deployment 资源对象 三、…

三、MySQL之创建和管理表

一、基础知识 1.1 一条数据存储的过程 存储数据是处理数据的第一步 。只有正确地把数据存储起来,我们才能进行有效的处理和分析。否则,只 能是一团乱麻,无从下手。 在 MySQL 中, 一个完整的数据存储过程总共有 4 步,分别是创建数据库、确认字段、创建数据表、插入数据。 …

基于SpringBoot Vue航空机票预订系统

大家好✌!我是Dwzun。很高兴你能来阅读我,我会陆续更新Java后端、前端、数据库、项目案例等相关知识点总结,还为大家分享优质的实战项目,本人在Java项目开发领域有多年的经验,陆续会更新更多优质的Java实战项目&#x…

【Linux与windows的文件互相传输】

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 关于 rzsz 注意事项 查看软件包 使用命令 下载到本地(使用sz的命令) 本地文件上传到Linux中(使用rz命令) 方法一…

无刷电机学习-方波电调 程序篇1(AM32)

一、AM32简介 AM32 固件专为 ARM 处理器设计,用于控制无刷电机 (BLDC)。该固件旨在安全、快速、平滑、快速启动和线性油门。它适用于多种车辆类型和飞行控制器。 AM32具有以下特点: 可通过 betaflight 直通、单线串行或 arduino 升级固件伺服 PWM、Dsh…

Druid集群搭建手册

1. Java环境安装和配置 建议使用JDK1.8。可以参考《Linux安装JDK完整步骤》。 2. 创建用户 创建druid用户,用来管理druid相关的服务。执行命令: useradd druid #创建用户 passwd druid #设置druid用户密码 3. Zookeeper安装和配置 Druid的服务套…

MySQL---多表分组查询综合练习

创建dept表 CREATE TABLE dept ( deptno INT(2) NOT NULL COMMENT 部门编号, dname VARCHAR (15) COMMENT 部门名称, loc VARCHAR (20) COMMENT 地理位置 ); 添加dept表主键 mysql> alter table dept add primary key(deptno); Query OK, 0 rows affected (0.02 s…

【手撕C语言 第六集】函数(上)

文章目录 一、函数是什么?二、C语言中函数的分类:1.库函数1.1 如何学会使用库函数? 2. 自定义函数 三、函数的参数1.实际参数(实参):2.形式参数(形参): 四、函数的调用&a…

深度学习-循环神经网络-RNN实现股价预测-LSTM自动生成文本

序列模型(Sequence Model) 基于文本内容及其前后信息进行预测 基于目标不同时刻状态进行预测 基于数据历史信息进行预测 序列模型:输入或者输出中包含有序列数据的模型 突出数据的前后序列关系 两大特点: 输入(输出)元素之间是具有顺序关系。不同的顺序,得到的结果应…

10分钟入手一套监控系统

写在前面的话 在这里,我将分享一些观测云的小技巧,让您能更好地注册、接入和利用免费额度。 pv每天是2000的免费额度,这里有个技巧,就是支持配置采样率,以1%的采样率来计算,每天也有20万的额度了就是采样设…

【方法】如何把Excel“只读方式”变成可直接编辑?

Excel在“只读方式”下,编辑后是无法直接保存原文件的,那如何可以直接编辑原文件呢?下面来一起看看看吧。 如果Excel设置的是无密码的“只读方式”,那在打开Excel后,会出现对话框,提示“是否以只读方式打开…

CTF CRYPTO 密码学-5

题目名称:山岚 题目描述: 山岚 f5-lf5aa9gc9{-8648cbfb4f979c-c2a851d6e5-c} 解题过程: Step1:根据题目提示栅栏加密 分析 观察给出的密文发现有f、l、a、g等字符有规律的夹杂的密文中间,看出都是每3个字符的第1…

「我在淘天做技术」智能对话新纪元:百万日活对话机器人的 LLM 落地实践

作者:智能小蜜团队 一、前言 阿里小蜜家族(阿里小蜜、店小蜜、万象),从 2015 年发展至今,已经成为了覆盖淘天 P-C(平台-消费者)、B-C(商家-消费者)、P-B(平台…