C#中如何订阅、处理并跟踪多个事件?(多设备场景下的实现咨询)
通用化多设备事件订阅的C#实现方案
我完全懂你的困扰——现在能单个设备订阅事件,但要扩展到多个设备时,重复写订阅代码不仅麻烦,还很容易搞混逻辑,毕竟socket.eventPool.Subscribe("flight", ...)这部分看起来都差不多。用类来封装每个设备的事件处理逻辑绝对是正确的方向,这样每个设备的订阅和业务逻辑都能独立管理,彻底避免混淆。
下面给你一套具体的实现方案,包含示例代码:
1. 先定义统一的处理器接口
首先我们给所有设备的flight事件处理器定义一个公共接口,保证结构一致,同时方便后续统一管理:
public interface IFlightEventHandler { // 返回当前处理器对应的设备名称 string TargetDevice { get; } // 每个设备专属的flight事件处理逻辑 void HandleFlightEvent(object sender, flightArgs e); }
2. 为每个设备实现专属处理器
接下来针对每个设备写具体的处理类,把该设备的业务逻辑完全封装在类里:
// Gulfstream设备的处理器 public class GulfstreamFlightHandler : IFlightEventHandler { public string TargetDevice => "gulfstream"; public void HandleFlightEvent(object sender, flightArgs e) { // Gulfstream专属逻辑:打印温度和高度 Console.WriteLine($"[Gulfstream] 实时数据:温度 {e.STR1.temp}°C,高度 {e.STR1.alt}ft"); } } // Boeing747设备的处理器 public class Boeing747FlightHandler : IFlightEventHandler { public string TargetDevice => "boeing747"; public void HandleFlightEvent(object sender, flightArgs e) { // Boeing747专属逻辑:打印数据+高度告警 Console.WriteLine($"[Boeing747] 实时数据:温度 {e.STR1.temp}°C,高度 {e.STR1.alt}ft"); CheckHighAltitudeWarning(e.STR1.alt); } private void CheckHighAltitudeWarning(double altitude) { if (altitude > 45000) { Console.WriteLine("[Boeing747] 告警:高度超过安全阈值!"); } } } // 后续新增设备只需要加新的处理器类就行,比如AirbusA380 public class AirbusA380FlightHandler : IFlightEventHandler { public string TargetDevice => "airbusa380"; public void HandleFlightEvent(object sender, flightArgs e) { // AirbusA380的专属逻辑,比如写入数据库或者调用其他接口 Console.WriteLine($"[AirbusA380] 记录数据:温度={e.STR1.temp},高度={e.STR1.alt}"); // SaveToDatabase(e); } }
3. 实现统一的事件管理器
写一个管理器类,负责把所有处理器注册到事件池,同时完成设备订阅。这样我们不需要重复写Subscribe和SubscribeEquip代码,所有逻辑都交给管理器处理:
public class FlightEventManager { private readonly Socket _socket; // 保存处理器和对应的委托,方便后续取消订阅 private readonly Dictionary<IFlightEventHandler, EventHandler<flightArgs>> _handlerDelegates = new(); public FlightEventManager(Socket socket) { _socket = socket; } public void RegisterHandler(IFlightEventHandler handler) { if (_handlerDelegates.ContainsKey(handler)) return; // 创建绑定当前处理器的委托,确保只处理目标设备的事件 var eventDelegate = new EventHandler<flightArgs>((sender, e) => { // 这里假设flightArgs里包含设备标识,如果没有的话,可能需要你调整socket库的事件参数,或者通过其他方式区分 // 如果实在无法从e中获取设备信息,也可以在订阅设备时通过闭包绑定,但这种方式依赖socket库的实现逻辑 if (e.DeviceName == handler.TargetDevice) { handler.HandleFlightEvent(sender, e); } }); // 订阅flight事件和对应的设备 _socket.eventPool.Subscribe("flight", eventDelegate); _socket.SubscribeEquip(handler.TargetDevice); // 保存委托,方便后续取消订阅 _handlerDelegates.Add(handler, eventDelegate); } public void UnregisterHandler(IFlightEventHandler handler) { if (_handlerDelegates.TryGetValue(handler, out var eventDelegate)) { // 取消事件订阅和设备订阅 _socket.eventPool.Unsubscribe("flight", eventDelegate); _socket.UnsubscribeEquip(handler.TargetDevice); _handlerDelegates.Remove(handler); } } }
4. 最终使用示例
在主代码里,只需要实例化管理器和各个处理器,注册进去就完成了所有设备的事件订阅:
// 假设你已经有了Socket实例 var socket = new Socket(); var flightEventManager = new FlightEventManager(socket); // 注册各个设备的处理器 flightEventManager.RegisterHandler(new GulfstreamFlightHandler()); flightEventManager.RegisterHandler(new Boeing747FlightHandler()); flightEventManager.RegisterHandler(new AirbusA380FlightHandler()); // 如果某个设备不需要监控了,直接取消注册 // flightEventManager.UnregisterHandler(boeingHandler);
额外优化建议
- 如果多个设备的处理逻辑有公共部分,可以抽一个抽象基类
BaseFlightEventHandler,把公共逻辑写在基类里,子类只需要重写差异化的部分。 - 如果
flightArgs里没有设备标识,你可以和socket库的提供者确认是否能添加,或者换一种方式:比如每个设备对应专属的事件名称(如flight_gulfstream),但这需要socket库支持。 - 别忘了在设备不再需要监控时调用
UnregisterHandler,避免内存泄漏。
这样一来,每个设备的逻辑都完全独立,新增设备只需要加一个处理器类,维护起来非常方便,再也不会出现逻辑混淆的问题了。
内容的提问来源于stack exchange,提问作者Blue Turkey
相关产品推荐
相关产品推荐

