C#实现异步的常用方式总结

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 methodtap模式)

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

public async task testdosomeasync()
  {
      await task.delay(1000);
      console.writeline("async method completed.");
  }

2、任务并行库(tpl, task parallel librarytap模式)

通过 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);
      }
  }

以上就是c#实现异步的常用方式总结的详细内容,更多关于c#异步的资料请关注硕编程其它相关文章!

下一节:c#synchronizationcontext以及send和post使用解读

c# 教程

相关文章