5

C#异步有多少种实现方式? - 追逐时光者

 1 year ago
source link: https://www.cnblogs.com/Can-daydayup/p/17383651.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

  微信群里的一个提问引发的这个问题,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);
        Console.WriteLine("Async method completed.");
    }

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

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

    public static async void Main(string[] args)
    {
        await Task.Run(() =>
        {
            Console.WriteLine("Test Task 1 completed.");
        });

        await Task.Run(() =>
        {
            Console.WriteLine("Test Task 2 completed.");
        });

        // 等待所有任务完成
        Task.WaitAll();
    }

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/

作者:追逐时光者

作者简介:一个热爱编程,善于分享,喜欢学习、探索、尝试新事物,新技术的程序猿。

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。如果该篇文章对您有帮助的话,可以点一下右下角的【♥推荐♥】,希望能够持续的为大家带来好的技术文章,文中可能存在描述不正确或错误的地方,欢迎指正、补充,不胜感激 !


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK