首页 > 编程语言 >C#异步有多少种实现方式?

C#异步有多少种实现方式?

时间:2023-05-15 14:01:16浏览次数:49  
标签:异步 Task C# 模式 public result 操作 多少

思维导航

前言

  微信群里的一个提问引发的这个问题,有同学问:C#异步有多少种实现方式?想要知道C#异步有多少种实现方式,首先我们要知道.NET提供的执行异步操作的三种模式,然后再去了解C#异步实现的方式。

.NET异步编程模式

.NET 提供了执行异步操作的三种模式:

  • 基于任务的异步模式 (TAP) ,该模式使用单一方法表示异步操作的开始和完成。 TAP 是在 .NET Framework 4 中引入的。 这是在 .NET 中进行异步编程的推荐方法。 C# 中的 async 和 await 关键词以及 Visual Basic 中的 Async 和 Await 运算符为 TAP 添加了语言支持。 有关详细信息,请参阅基于任务的异步模式 (TAP)

  • 基于事件的异步模式 (EAP),是提供异步行为的基于事件的旧模型。 这种模式需要后缀为 Async 的方法,以及一个或多个事件、事件处理程序委托类型和 EventArg 派生类型。 EAP 是在 .NET Framework 2.0 中引入的。 建议新开发中不再使用这种模式。 有关详细信息,请参阅基于事件的异步模式 (EAP)

  • 异步编程模型 (APM) 模式(也称为 IAsyncResult 模式),这是使用 IAsyncResult 接口提供异步行为的旧模型。 在这种模式下,同步操作需要 Begin 和 End 方法(例如,BeginWrite 和 EndWrite以实现异步写入操作)。 不建议新的开发使用此模式。 有关详细信息,请参阅异步编程模型 (APM)

C#异步有四种实现方式

C# 异步有多种实现方式,可归纳为以下几类:

1、异步方法(Async Method TAP模式

使用async/await关键字实现异步编程,这是比较常用的一种异步实现方式。例如:

    public async Task TestDoSomeAsync()
    {
        await Task.Delay(1000*10);
        Console.WriteLine("Async method completed.");
    }

2、任务并行库(TPL, Task Parallel Library TAP模式

通过 Task 和 Task<T> 类型实现异步编程,可以利用多核处理器,并发执行多个独立的任务。例如:

复制代码
        public static void TestTaskParallel()
        {
            var task1 = Task.Run(() =>
            {
                Console.WriteLine("Task 1 completed.");
            });

            var task2 = Task.Run(() =>
            {
                Console.WriteLine("Task 2 completed.");
            });

            Task<int> task3 = Task.Factory.StartNew(() =>
            {
                Console.WriteLine("Task 3 completed.");
                return 20;// 返回一个整数值
            });

            //等待所有任务完成
            Task.WaitAll(task1, task2, task3);
        }
复制代码

3、Asynchronous Programming Model(APM模式)

是一种经典的异步编程模式,需要手动创建回调函数,用于处理完成或错误的通知。可以通过 IAsyncResult 设计模式的 Begin 和 End 方法来实现,其中 Begin 方法开始异步操作,而 End 方法在异步操作完成时执行,并返回异步操作的结果。

需要注意的是,APM 模式通过 IAsyncResult 接口来存储异步操作的状态和结果,相对比较复杂,代码量也较大。同时,在使用 APM 模式时,还需要手动处理回调函数和等待异步操作完成等细节工作,使得开发起来相对较为繁琐。

复制代码
    class Program
    {
        static void Main(string[] args)
        {
            // 创建异步操作类实例
            MyAsyncClass asyncClass = new MyAsyncClass();

            // 开始异步操作
            IAsyncResult result = asyncClass.BeginDoWork(null, null);

            // 主线程执行其他操作
            // 等待异步操作完成并获取结果
            int res = asyncClass.EndDoWork(result);

            // 处理异步操作的结果
            Console.WriteLine("Result: " + res);

            Console.ReadLine();
        }
    }

    class MyAsyncClass
    {
        /// <summary>
        /// 异步执行的方法
        /// </summary>
        /// <param name="callback">callback</param>
        /// <param name="state">state</param>
        /// <returns></returns>
        public IAsyncResult BeginDoWork(AsyncCallback callback, object state)
        {
            // 创建一个新的异步操作对象
            MyAsyncResult result = new MyAsyncResult(state);

            // 开始异步操作
            Thread thread = new Thread(() =>
            {
                try
                {
                    // 执行一些操作
                    int res = 1 + 2;

                    // 设置异步操作的结果
                    result.Result = res;

                    // 触发回调函数
                    callback?.Invoke(result);
                }
                catch (Exception ex)
                {
                    // 设置异步操作的异常
                    result.Error = ex;

                    // 触发回调函数
                    callback?.Invoke(result);
                }

            });
            thread.Start();

            // 返回异步操作对象
            return result;
        }

        /// <summary>
        /// 结束异步执行的方法
        /// </summary>
        /// <param name="result">result</param>
        /// <returns></returns>
        public int EndDoWork(IAsyncResult result)
        {
            // 将 IAsyncResult 转换为 MyAsyncResult 类型,并等待异步操作完成
            MyAsyncResult myResult = (MyAsyncResult)result;
            myResult.AsyncWaitHandle.WaitOne();

            // 在异步操作中抛出异常
            if (myResult.Error != null)
            {
                throw myResult.Error;
            }

            // 返回异步操作的结果
            return myResult.Result;
        }
    }

    class MyAsyncResult : IAsyncResult
    {
        public bool IsCompleted => AsyncWaitHandle.WaitOne(0);
        public WaitHandle AsyncWaitHandle { get; } = new ManualResetEvent(false);
        public object AsyncState { get; }
        public bool CompletedSynchronously => false;

        public int Result { get; set; }

        /// <summary>
        /// 存储异步操作的结果或异常信息
        /// </summary>
        public Exception Error { get; set; }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="asyncState">asyncState</param>
        public MyAsyncResult(object asyncState)
        {
            AsyncState = asyncState;
        }
    }
复制代码

4、Event-based Asynchronous Pattern(EAP模式)

一种已过时的异步编程模式,需要使用事件来实现异步编程。例如:

需要注意的是,EAP 模式通过事件来实现异步编程,相对于 APM 模式更加简洁易懂,同时也避免了手动处理回调函数等细节工作。但是,EAP 模式并不支持 async/await 异步关键字,因此在一些特定的场景下可能不够灵活。

复制代码
public class MyAsyncClass : Component
    {
        /// <summary>
        /// 声明一个委托类型,用于定义异步操作的方法签名
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        public delegate int MyAsyncDelegate(int arg);

        /// <summary>
        /// 声明一个事件,用于通知异步操作的完成
        /// </summary>
        public event MyAsyncDelegate OperationNameCompleted;

        /// <summary>
        /// 异步执行方法,接受一个参数 arg
        /// </summary>
        /// <param name="arg"></param>
        public void DoWorkAsync(int arg)
        {
            // 将异步操作放入线程池中执行
            ThreadPool.QueueUserWorkItem(new WaitCallback(DoWork), arg);
        }

        /// <summary>
        /// 真正的异步操作
        /// </summary>
        /// <param name="obj"></param>
        private void DoWork(object obj)
        {
            int arg = (int)obj;
            int res = arg + 1;

            // 触发事件,传递异步操作的结果
            OperationNameCompleted?.Invoke(res);
        }
    }
复制代码

参考文章

https://learn.microsoft.com/zh-cn/dotnet/standard/asynchronous-programming-patterns/

 

出处:https://www.cnblogs.com/Can-daydayup/p/17383651.html

标签:异步,Task,C#,模式,public,result,操作,多少
From: https://www.cnblogs.com/mq0036/p/17401659.html

相关文章

  • java.lang.reflect 包
    java.lang.reflect包提供了反射中用到类,主要的类说明如下:Constructor类:提供类的构造方法信息。Field类:提供类或接口中成员变量信息。Method类:提供类或接口成员方法信息。Array类:提供了动态创建和访问Java数组的方法。Modifier类:提供类和成员访问修饰符信息。......
  • 无感FOC 基于DSP28335平台的无感FOC算法 代码包括了
    无感FOC基于DSP28335平台的无感FOC算法代码包括了完整的矢量控制算法,在smo的基础上,增加了VESC原始的磁链观测器,还增加了磁链观测器+PLL方案,还增加了增量编码器的接口代码,方便大家调试无感算法。每个环节都是在实物上跑过的,转子位置角度通过全局变量设置进行任意的切换,算法之间相互......
  • MATLAB 微网优化调度 两阶段鲁棒 CCG算法 经济调度 参考文档:《微电网
    MATLAB微网优化调度两阶段鲁棒CCG算法经济调度参考文档:《微电网两阶段鲁棒优化经济调度方法》仿真平台:MATLABYALMIP+CPLEX优势:代码注释详实,出图效果非常好(具体看图),非目前烂大街版本,请仔细辨识!主要内容:构建了微网两阶段鲁棒调度模型,建立了min-max-min结构的两阶段鲁棒优化模......
  • MD500E源码和代码解析文档 代码包含了同步机FOC控制算法、电阻、电感、磁
    MD500E源码和代码解析文档代码包含了同步机FOC控制算法、电阻、电感、磁链、反电动势、死区补偿、过调制限制、弱磁等算法,支持无感和有感,带电机运行过。ID:6916673083572622......
  • execjs - 编码报错问题解决方案
    当在Python中运行execjs时遇到编码问题,可能是由于JS代码中使用了非UTF-8编码。为了解决这个问题,您可以尝试以下两种方案最直接方法需要修改Subprocess中的Enconding为"Utf-8"将JS代码转换为UTF-8编码您可以在JS代码中将所有字符串转换为UTF-8编码。例如,您可以在JS代码文件......
  • 电动车电池bms电池管理系统 锂电池算法SOC代码 获取锂电池SOC采用的是
    电动车电池bms电池管理系统锂电池算法SOC代码获取锂电池SOC采用的是电流积分法,电化学阻抗法电流积分法又称为安时积分法或库伦计数,通过将电池电流对时间进行积分来计算电池的荷电状态。这种方法对于计算电池放出的电量有一定的准确度,但缺乏参照点,不能计算电池的初始SOC,也无法预......
  • Sata/世达大厂正弦波电动自行车控制器量产资料,包括源码和原理图pcb
    Sata/世达大厂正弦波电动自行车控制器量产资料,包括源码和原理图pcb源头代码,提供一定和相关配套ID:1780684041831000......
  • logack 简介
    转载:https://juejin.cn/post/6844903641535479821之前在日志?聊一聊slf4j吧这篇文章中聊了下slf4j。本文也从实际的例子出发,针对logback的日志配置进行学习。logack简介logback官网:https://logback.qos.ch/目前还没有看过日志类框架的源码,仅限于如何使用。所以就不说......
  • 车载充电器 3.3KW 车载充电机OBC方案 方案:PFC两相交
    车载充电器3.3KW车载充电机OBC方案方案:PFC两相交错并联,Dc全桥LLC,28035控制,CAN通信。文件内容:原理图Pcb关键磁件参数源代码实用范围:项目参考借鉴学习,不具备量产功能。ID:16146684069616387......
  • 使用MASA Stack+.Net 从零开始搭建IoT平台 第四章 4.1处理设备上行数据-获取并通知业
    目录前言分析方案共享订阅带群组的共享订阅均衡分发策略数据格式实施流程编写代码验证效果总结前言物联网平台首先需要可以获取并处理设备上报的MQTT中的数据,我们称这部分为上行数据。本章将分为三小节。1、通过MQTT获取设备上报数据并通知业务系统2、业务系统存储和处理上......