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


    前言

      微信群里的一个提问引发的这个问题,有同学问: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 类型实现异步编程,可以利用多核处理器,并发执行多个独立的任务。例如:

    复制代码
            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
        {
            /// 
            /// 异步执行的方法
            /// 
            /// callback
            /// state
            /// 
            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;
            }
    
            /// 
            /// 结束异步执行的方法
            /// 
            /// result
            /// 
            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; }
    
            /// 
            /// 存储异步操作的结果或异常信息
            /// 
            public Exception Error { get; set; }
    
            /// 
            /// 构造函数
            /// 
            /// asyncState
            public MyAsyncResult(object asyncState)
            {
                AsyncState = asyncState;
            }
        }
    复制代码

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

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

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

    复制代码
    public class MyAsyncClass : Component
        {
            /// 
            /// 声明一个委托类型,用于定义异步操作的方法签名
            /// 
            /// 
            /// 
            public delegate int MyAsyncDelegate(int arg);
    
            /// 
            /// 声明一个事件,用于通知异步操作的完成
            /// 
            public event MyAsyncDelegate OperationNameCompleted;
    
            /// 
            /// 异步执行方法,接受一个参数 arg
            /// 
            /// 
            public void DoWorkAsync(int arg)
            {
                // 将异步操作放入线程池中执行
                ThreadPool.QueueUserWorkItem(new WaitCallback(DoWork), arg);
            }
    
            /// 
            /// 真正的异步操作
            /// 
            /// 
            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/

     

     

  • 相关阅读:
    缓存同步之 RabbitMQ 和 Canal
    springAOP讲解
    「运维有小邓」如何更有效的避免密码攻击
    MongoDB 安装报错:无法启动此程序,缺少dll文件
    时序预测 | MATLAB实现CNN-GRU卷积门控循环单元时间序列预测(风电功率预测)
    安卓手机APP开发__媒体开发部分__播放器的接口
    Spring MVC组件之HandlerMapping
    MySQL表的CURD
    VUEX版数字求和案例,附带vuex工作执行顺序图
    共享内存 - 多进程编程(三)
  • 原文地址:https://www.cnblogs.com/Can-daydayup/p/17383651.html