如何在ASP.NET Core中使用delegate定义、触发和处理异步事件
异步事件(Async Events)的正确使用方式
一、核心概念梳理
异步事件本质是支持异步处理逻辑的事件系统,完全不需要强制使用静态类做处理程序——只要你的处理程序类能被实例化,就能注入依赖并完成事件注册。.NET框架提供了现成的AsyncEventHandler<TEventArgs>委托类型,专门用来定义异步事件,无需自定义基础委托。
二、分步示例实现
下面用「订单创建事件 + 带日志依赖的异步处理」场景做演示:
1. 定义事件参数类
创建事件触发时传递数据的类:
// 事件参数:传递订单创建的相关信息 public class OrderCreatedEventArgs : EventArgs { public int OrderId { get; } public decimal Amount { get; } public OrderCreatedEventArgs(int orderId, decimal amount) { OrderId = orderId; Amount = amount; } }
2. 创建事件发布者(触发事件的类)
定义负责触发事件的服务,用AsyncEventHandler<TEventArgs>声明事件:
public class OrderService { // 声明异步事件:使用框架自带的AsyncEventHandler<T> public event AsyncEventHandler<OrderCreatedEventArgs>? OrderCreated; // 模拟创建订单的方法,完成后触发事件 public async Task CreateOrderAsync(int orderId, decimal amount) { // 模拟订单创建的异步业务逻辑 await Task.Delay(100); // 触发事件:先判断是否有订阅者,再异步调用 if (OrderCreated != null) { await OrderCreated.Invoke(this, new OrderCreatedEventArgs(orderId, amount)); } } }
3. 创建带依赖的事件处理程序
处理程序类包含依赖(比如日志服务),并实现异步处理逻辑:
// 模拟日志服务接口 public interface ILogger { Task LogAsync(string message); } // 模拟日志服务实现 public class ConsoleLogger : ILogger { public async Task LogAsync(string message) { await Task.Delay(50); // 模拟异步日志写入 Console.WriteLine($"[日志] {message}"); } } // 带依赖的事件处理类 public class OrderCreatedHandler { private readonly ILogger _logger; // 通过构造函数注入依赖 public OrderCreatedHandler(ILogger logger) { _logger = logger; } // 异步事件处理方法:签名匹配AsyncEventHandler<T> public async Task HandleOrderCreatedAsync(object? sender, OrderCreatedEventArgs e) { // 每次事件触发时执行的逻辑 await _logger.LogAsync($"订单 {e.OrderId} 已创建,金额:{e.Amount:C}"); // 可添加其他异步操作:比如发送通知、更新统计数据等 await Task.Delay(200); } }
4. 注册事件并触发
在主程序中完成依赖初始化、事件注册和触发:
class Program { static async Task Main(string[] args) { // 1. 实例化依赖服务 ILogger logger = new ConsoleLogger(); // 2. 实例化带依赖的处理程序 OrderCreatedHandler handler = new OrderCreatedHandler(logger); // 3. 实例化事件发布者 OrderService orderService = new OrderService(); // 4. 注册事件:将处理程序的方法绑定到事件 orderService.OrderCreated += handler.HandleOrderCreatedAsync; // 5. 触发事件:模拟创建两个订单 await orderService.CreateOrderAsync(1001, 299.99m); await orderService.CreateOrderAsync(1002, 59.9m); Console.ReadLine(); } }
三、关键注意事项
- 异步事件触发必须用await:如果直接调用
OrderCreated?.Invoke(...)不await,会导致异步操作未完成就继续执行后续代码,还可能引发未捕获的异常。 - 抛弃静态类误区:处理程序可以是实例类,通过构造函数注入依赖,注册事件时直接绑定实例方法即可。
- 空事件判断:触发事件前一定要检查
OrderCreated != null,避免空引用异常。 - 多订阅者处理:多个处理程序注册到同一事件时,默认会串行异步执行,若需要并行可自行实现逻辑。
内容的提问来源于stack exchange,提问作者Szyszka947
相关产品推荐
相关产品推荐

