C#实现异步的常用方式总结
作者:追逐时光者 发布时间:2023-10-26 17:25:13
前言
微信群里的一个提问引发的这个问题,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://www.cnblogs.com/Can-daydayup/p/17383651.html


猜你喜欢
- 本小节内容不多,但是个人感觉比较独立,还是拿出来单讲吧。在开发 IntelliJ Plugin 时,如果需要用到 Gson、OKHttp 等
- dynamic是FrameWork4.0的新特性。dynamic的出现让C#具有了弱语言类型的特性。编译器在编译的时候不再对类型进行检查,编
- W3C制定了XML DOM标准,.Net为了支持W3C的标准,从1.1版本开始就引入了XmlDocument类。我在前一篇博客中,介绍了如何
- 生成文字图片:/// <summary> /// 生成文字图片 /// &l
- 废话不多说了,先给大家上左右无限滑动的代码了。1.左右无限滑动public class MainActivity extends AppCo
- 后端接收form-data创建实体类public class Para_list //实体类 { &n
- 一、效果图:二、导入 jar 包1.由于这是大神写好封装起来的一个框架,所有我们使用前得先下载相关的 jar 包第一种:maven<!
- 本文实例讲述了C#遍历指定目录下所有文件的方法。分享给大家供大家参考。具体分析如下:先通过DirectoryInfo打开指定的目录,然后通过
- --删除外键 语法:alter table 表名 drop constraint 外键约束名 如: alter table Stu_PkFk
- 在逆向一个Android程序时,如果只是盲目的分析需要阅读N多代码才能找到程序的关键点或Hook点,本文将分享一下如何快速的找到APP程序的
- Javaweb开发环境的配置也是比较繁琐的一件事情,虽然理论上使用记事本,完全可以写出一个Javaweb工程,但是在团队大型开发的Javaw
- 本文解析了C# KeyUp事件中MessageBox的回车(Enter)键出现回调问题的解决办法。具体问题如下:在一个窗体上有一个名为txt
- 前言在Android开发过程中,Bitmap往往会给开发者带来一些困扰,因为对Bitmap操作不慎,就容易造成OOM(Java.lang.O
- 在之前文章的铺垫下,再为大家分享一篇:Android手势密码,附源码下载,不要错过。源码下载:http://xiazai.jb51.net/
- Unity脚本自动添加头部注释就是创建.cs文件时自动添加作者名,创建时间,文件名等看示例,我们在Unity的project面板下先创建一个
- 介绍我们都知道函数是程序中的基本模块,代码段。那高阶函数呢?听起来很好理解吧,就是函数的高阶(级)版本。它怎么高阶了呢?我们来看下它的基本定
- struct InputStream 是单个输入流的管理器。是由 add_input_stream() 函数申
- 本文实例讲述了Android开发之文件操作。分享给大家供大家参考,具体如下:目前,几乎所有的设备都会涉及到文件的操作,例如什么电脑,手机等设
- 本文实例讲述了Android编程实现TextView部分颜色变动的方法。分享给大家供大家参考,具体如下:public class Strin
- 导出Excel的框架有很多种,POI相对来说比较老了,很多Excel框架底层都是POI、有EasyPoi、EasyExcel、包括Hutoo