.NET异步有多少种实现方式?(异步编程提高系统性能、改善用户体验)

简介: 想要知道.NET异步有多少种实现方式,首先我们要知道.NET提供的执行异步操作的三种模式,然后再去了解.NET异步实现的四种方式。

前言

想要知道.NET异步有多少种实现方式,首先我们要知道.NET提供的执行异步操作的三种模式,然后再去了解.NET异步实现的四种方式。

.NET执行异步操作的三种模式

  • 基于任务的异步模式 (TAP)【推荐使用】 :该模式使用单一方法表示异步操作的开始和完成,TAP 是在 .NET Framework 4 中引入的。这是在 .NET 中进行异步编程的推荐方法。 C# 中的 asyncawait 关键词以及 Visual Basic 中的 AsyncAwait 运算符为 TAP 添加了语言支持。有关详细信息,请参阅基于任务的异步模式 (TAP)
  • 基于事件的异步模式 (EAP):是提供异步行为的基于事件的旧模型, 这种模式需要后缀为 Async 的方法,以及一个或多个事件、事件处理程序委托类型和 EventArg 派生类型。EAP 是在 .NET Framework 2.0 中引入的。建议新开发中不再使用这种模式。有关详细信息,请参阅基于事件的异步模式 (EAP)
  • 异步编程模型 (APM) 模式(也称为 IAsyncResult 模式):这是使用 IAsyncResult 接口提供异步行为的旧模型, 在这种模式下,同步操作需要 Begin 和 End 方法(例如,BeginWrite 和 EndWrite以实现异步写入操作)。不建议新的开发使用此模式。有关详细信息,请参阅异步编程模型 (APM)

.NET异步编程有什么作用?

  • 提高性能和资源利用率:异步编程可以在等待 I/O 操作完成的同时释放线程资源,使得线程能够继续执行其他任务,从而提高了系统的资源利用率和性能。
  • 改善用户体验:通过异步编程,可以避免在等待长时间操作完成时出现界面卡顿或无响应的情况,从而改善用户体验,使应用程序更加流畅和响应。
  • 简化编程模型:使用 C# 提供的asyncawait 关键字可以使异步编程变得更加简洁和易于理解,避免了传统的回调地狱(callback hell),使代码更具可读性和可维护性。
  • 提高并发性:通过异步编程,可以更有效地处理并发请求,从而提高系统的并发性能,使得应用程序能够更好地处理大量用户请求。
  • 支持大规模并行编程:异步编程模型使得在大规模并行编程中更容易管理和控制异步任务的执行,提供了更灵活的并发编程方式。

总的来说,异步编程在提高系统性能、改善用户体验、简化编程模型和支持并行编程方面发挥着重要作用,是现代软件开发中不可或缺的重要技术之一。

一、异步方法(Async Method TAP模式)

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

/// <summary>
        /// 异步方法(Async Method TAP模式)
        /// </summary>
        /// <returns></returns>
        public static async Task TestDoSomeAsync()
        {
            await Task.Delay(1000 * 10).ConfigureAwait(false); //等待10秒
            Console.WriteLine("Async Method Completed.");
        }

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

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

/// <summary>
        /// 任务并行库(TPL, Task Parallel Library TAP模式)
        /// </summary>
        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);
        }

三、Asynchronous Programming Model(APM模式)

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

注意:在 .NET Core 或 .NET 5+ 等新版本中,BeginInvoke 方法已经被弃用并不再支持,因此可能会导致 System.PlatformNotSupportedException 异常,不过在.NET FX环境是支持的。

/// <summary>
        /// Asynchronous Programming Model(APM模式)
        /// </summary>
        public static void TestAPMAsync()
        {
            // 创建一个 AsyncCallback 委托,用于处理异步操作完成后的回调
            var callback = new AsyncCallback(AsyncOperationCallback);
            // 创建一个异步委托实例,表示要异步执行的操作
            var asyncMethod = new Func<int, string>(AsyncMethod);
            // 开始异步操作
            var result = asyncMethod.BeginInvoke(88, callback, asyncMethod);
            Console.WriteLine($"TestAPMAsync Completed.");
            Console.ReadLine();
        }
        private static string AsyncMethod(int parameter)
        {
            Console.WriteLine("AsyncMethod开始执行了...");
            return $"异步操作完成,参数为:{parameter}。";
        }
        private static void AsyncOperationCallback(IAsyncResult result)
        {
            try
            {
                // 从异步状态对象中获取返回的异步委托
                Func<int, string> asyncMethod = (Func<int, string>)result.AsyncState;
                string message = asyncMethod.EndInvoke(result);
                Console.WriteLine(message);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"异步操作发生异常:{ex.Message}");
            }
        }

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

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

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

/// <summary>
        /// Event-based Asynchronous Pattern(EAP模式)
        /// </summary>
        static void Main(string[] args)
        {
            var asyncObj = new MyAsyncClass();
            // 订阅异步操作完成事件
            asyncObj.OperationNameCompleted += AsyncObjOperationNameCompleted;
            // 启动异步操作
            asyncObj.DoWorkAsync(10);
            Console.ReadLine();
        }
        /// <summary>
        /// 异步操作完成事件的处理方法
        /// </summary>
        /// <param name="result">result</param>
        private static void AsyncObjOperationNameCompleted(int result)
        {
            Console.WriteLine($"异步操作完成,结果为: {result}");
        }
        public class MyAsyncClass : Component
        {
            /// <summary>
            /// 声明一个委托类型,用于定义异步操作的方法签名
            /// </summary>
            /// <param name="arg"></param>
            /// <returns></returns>
            public delegate void 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);
            }
        }

拾遗补漏合集

在这个快速发展的技术世界中,时常会有一些重要的知识点、信息或细节被忽略或遗漏。《C#/.NET/.NET Core拾遗补漏》专栏我们将探讨一些可能被忽略或遗漏的重要知识点、信息或细节,以帮助大家更全面地了解这些技术栈的特性和发展方向。

GitHub开源地址

https://github.com/YSGStudyHards/DotNetGuide/blob/main/docs/DotNet/DotNetStudy.md

拾遗补漏知识点投稿

该Issues主要是给各位小伙伴们提供投稿的地方,你有什么想要学习的C#/.NET/.NET Core相关技术栈或者已学习过且有文章输出的欢迎在投稿!

https://github.com/YSGStudyHards/DotNetGuide/issues/37

相关文章
|
1月前
|
消息中间件 前端开发 小程序
一个基于.NET Core构建的简单、跨平台、模块化的商城系统
今天大姚给大家分享一个基于.NET Core构建的简单、跨平台、模块化、完全开源免费(MIT License)的商城系统:Module Shop。
|
1月前
|
小程序 C# 数据库
3个.NET开源、免费、强大的商城系统
今天大姚给大家分享3个.NET开源、免费、强大的商城系统,希望可以帮助到有商城系统开发需求的同学。
|
1月前
|
开发框架 Oracle 关系型数据库
ASP.NET实验室LIS系统源码 Oracle数据库
LIS是HIS的一个组成部分,通过与HIS的无缝连接可以共享HIS中的信息资源,使检验科能与门诊部、住院部、财务科和临床科室等全院各部门之间协同工作。 
49 4
|
10天前
|
开发框架 前端开发 .NET
LIMS(实验室)信息管理系统源码、有哪些应用领域?采用C# ASP.NET dotnet 3.5 开发的一套实验室信息系统源码
集成于VS 2019,EXT.NET前端和ASP.NET后端,搭配MSSQL 2018数据库。系统覆盖样品管理、数据分析、报表和项目管理等实验室全流程。应用广泛,包括生产质检(如石化、制药)、环保监测、试验研究等领域。随着技术发展,现代LIMS还融合了临床、电子实验室笔记本和SaaS等功能,以满足复杂多样的实验室管理需求。
21 3
LIMS(实验室)信息管理系统源码、有哪些应用领域?采用C# ASP.NET dotnet 3.5 开发的一套实验室信息系统源码
|
3天前
|
前端开发 测试技术 C#
如何开发一套基于C#和.NET 6.0手术麻醉系统? 手术麻醉系统源码
如何开发一套基于C#和.NET 6.0手术麻醉系统?
12 1
|
22天前
|
设计模式 存储 编译器
【.NET Core】异步编程模式
【.NET Core】异步编程模式
21 2
|
22天前
|
开发框架 .NET 对象存储
【.NET Core】深入理解异步编程模型(APM)
【.NET Core】深入理解异步编程模型(APM)
21 1
|
30天前
|
安全 API C#
C#.Net筑基-类型系统②常见类型--枚举Enum
枚举(enum)是C#中的一种值类型,用于创建一组命名的整数常量。它们基于整数类型(如int、byte等),默认为int。枚举成员可指定值,未指定则从0开始自动递增。默认值为0。枚举可以与整数类型互相转换,并可通过`[Flags]`特性表示位域,支持位操作,用于多选场景。`System.Enum`类提供了如`HasFlag`、`GetName`等方法进行枚举操作。
|
30天前
|
编译器 C#
C#.Net筑基-类型系统②常见类型 --record是什么类型?
`record`在C#中是一种创建简单、只读数据结构的方式,常用于轻量级数据传输。它本质上是类(默认)或结构体的快捷形式,包含自动生成的属性、`Equals`、`ToString`、解构赋值等方法。记录类型可以继承其他record或接口,但不继承普通类。支持使用`with`语句创建副本。例如,`public record User(string Name, int Age)`会被编译为包含属性、相等比较和`ToString()`等方法的类。记录类型提供了解构赋值和自定义实现,如密封的`sealed`记录,防止子类重写。
|
30天前
|
存储 C#
C#.Net筑基-类型系统②常见类型--结构体类型Struct
本文介绍了C#中的结构体(struct)是一种用户自定义的值类型,适用于定义简单数据结构。结构体可以有构造函数,能定义字段、属性和方法,但不能有终结器或继承其他类。它们在栈上分配,参数传递为值传递,但在类成员或包含引用类型字段时例外。文章还提到了`readonly struct`和`ref struct`,前者要求所有字段为只读,后者强制结构体存储在栈上,适用于高性能场景,如Span和ReadOnlySpan。