前言
异步是指程序的一种执行模式,它与同步相对。在同步执行模式下,程序按照代码编写的顺序一步步执行,每个操作都要等待上一个操作完成后才能继续执行。在异步执行模式下,程序可以在一个操作执行的同时,继续执行另一个操作,而不需要等待前一个操作完成。
在编程中,异步通常用于需要耗时操作的场景,例如网络请求、文件读写等。如果这些操作在同步模式下执行,会阻塞程序的运行,影响用户体验。而以异步模式执行,可以让程序在执行耗时操作的同时,继续响应用户的请求,提高程序的运行效率。同时,异步也可以提高代码的可维护性,使代码更加简洁易懂。
一、异步四种实现方式
.NET 提供了以下三种执行异步操作的模式:
1、基于任务的异步模式 (TAP)
.NET中基于任务的异步模式 (Task-based Asynchronous Pattern,TAP) 是一种基于 .NET 异步编程模型的规范,它使用 Task 和 Task<TResult> 类封装异步操作,使得异步编程更加简单、可读性更高。TAP 模式主要包含以下几个方面:
- 异步方法返回 Task 或 Task<TResult> 对象,并使用 async 关键字标记方法为异步方法。
- 异步方法通常采用异步函数体的方式实现,使用 await 关键字等待异步操作的完成。
- 异步方法具有一定的错误处理机制,可以通过捕获异常来处理异步操作中的错误。
- TAP 模式支持通过 CancellationToken 取消异步操作。
通过使用 TAP 模式,可以让异步编程更加符合 C# 语言特性,使得异步代码更加易于维护和扩展。在 .NET 中,很多异步 API 都采用了 TAP 模式。例如,File 类的 ReadAsync 和 WriteAsync 方法,HttpClient 类的 GetAsync 和 PostAsync 方法等等。
2、基于事件的异步模式 (EAP)
基于事件的异步模式 (EAP) 是 .NET 框架的一种异步编程模型,它允许开发者在执行异步操作时通过事件订阅模式来处理异步操作的完成通知和异常处理。使用 EAP,开发者可以创建事件处理器来处理异步操作所引发的事件,而不需要使用回调函数或等待异步操作完成。
在 EAP 中,异步操作由两个方法组成:异步方法和完成事件触发方法。异步方法通常以异步方式启动操作,同时返回 void 或者一个 Task 对象。完成事件触发方法则在异步操作完成时被触发,传递异步操作结果和异常信息。
EAP 在 .NET 4.5 之后不再被视为首选的异步编程模式,而是被 Task-based asynchronous pattern (TAP) 所取代。尽管如此,仍然有一些基于 EAP 的 API 在 .NET 框架中得到广泛应用,例如 System.Net.WebRequest 和 System.ComponentModel.BackgroundWorker 等。
3、异步编程模型 (APM) 模式(也称为 IAsyncResult 模式)
异步编程模型 (APM) 是在 .NET 中进行异步编程的一种方式。该模式基于 IAsyncResult 接口和 BeginXXX/EndXXX 方法对异步操作进行管理。
在 APM 模式中,异步操作的开始通常由 BeginXXX 方法触发。该方法会返回一个 IAsyncResult 接口对象,它包含了异步操作的状态信息。同时,该方法会将异步操作交给一个线程池线程去执行,而不会阻塞当前线程。
异步操作完成后,EndXXX 方法会被调用。该方法需要传入 BeginXXX 方法返回的 IAsyncResult 对象,并返回异步操作的结果。如果异步操作尚未完成,EndXXX 方法会等待操作完成后再返回。
APM 模式需要开发人员手动管理线程池线程,包括对线程池线程的数量和优先级进行管理。在 .NET 4.5 之后,APM 模式已经被 Task-based Asynchronous Pattern (TAP) 取代,TAP 模式是一种更简单、更可读的异步编程模式。
1.异步方法(Async Method TAP模式)
代码语言:c#复制public async Task TestDoSomeAsync()
{
await Task.Delay(1000*10);
Console.WriteLine("Async method completed.");
}
2.任务并行库(TPL, Task Parallel Library TAP模式)
代码语言:c#复制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模式)
代码语言:c#复制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模式)
代码语言:c#复制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);
}
}
总结
TAP(Test Anything Protocol)是一种通信协议,用于测试框架和测试工具之间的通信,以便更好地跟踪和报告测试结果。TAP通常用于自动化测试,如单元测试、集成测试等。
EAP(Extensible Authentication Protocol)是一种网络认证协议,用于在客户端和网络访问服务器之间进行安全认证。EAP通常用于WPA(Wi-Fi Protected Access)和802.1X认证中。
EAP适用场景包括需要进行网络认证的场景,如企业无线网络、VPN等。EAP支持多种认证方式,如密码认证、数字证书认证、智能卡认证等,可以根据实际需要选择适合的认证方式。
【选题思路】
异步编程的应用场景较多,并且可以显著提高程序的性能和响应速度。比如:
- 提高程序的性能:异步编程可以执行非阻塞式I/O操作,同时处理多个请求,提高程序的性能。
- 提高用户体验:通过异步编程,可以更快地响应用户的操作,提高用户体验。
- 优化资源利用:异步编程可以让程序更有效地利用资源,例如CPU和网络连接,提高系统的效率。
- 实现并发处理:异步编程可以同时处理多个任务,实现并发处理,从而提高程序的可扩展性和并发性能。
- 适用于大量数据处理:异步编程可以用于处理大量的数据,例如图像和视频数据,处理效率高。 异步编程是一种高效的编程方式,在许多应用场景中可以发挥巨大作用。对于开发者而言,掌握异步编程能够提高开发效率,同时提高程序的性能和用户体验。
【创作提纲】
1、异步方法(Async Method TAP模式)
2、任务并行库(TPL, Task Parallel Library TAP模式)
3、Asynchronous Programming Model(APM模式)
4、Event-based Asynchronous Pattern(EAP模式)