C#跨类订阅网络事件触发问题:如何实现事件正常触发?
我来帮你梳理下问题所在,以及对应的修复方案:
1. 修复Class B中getHandler方法的核心错误
你在getHandler里写的EventHandlers[code] += 'eventHandlerMethodeOne';是完全错误的——委托只能添加方法的委托实例,不能直接拼接字符串(这行代码甚至应该编译失败)。正确逻辑应该是:如果指定索引的委托为空,就初始化一个空委托(避免后续订阅时出现空引用异常),再返回它让Class A能正确绑定:
public EventHandler<CustomEventArgs> getHandler(int code) { // 可选但推荐:增加索引合法性检查,避免数组越界 if (code < 0 || code >= EventHandlers.Length) { throw new ArgumentOutOfRangeException(nameof(code), "事件代码超出数组范围"); } if (EventHandlers[code] == null) { // 初始化空委托,确保订阅操作不会因为null而失败 EventHandlers[code] = delegate { }; } return EventHandlers[code]; }
2. 补充Class B的事件触发逻辑
你提到Class B负责处理并触发事件,但没写出具体触发代码。当接收端解析到消息后,必须主动调用对应委托的Invoke方法,才能触发Class A订阅的事件。示例代码如下:
// 假设这是Class B接收并处理消息的核心方法 private void ProcessReceivedMessage(byte[] receivedBuffer) { // 严格按照发送端的字节结构解析 int sender = BitConverter.ToInt32(receivedBuffer, 0); int receiver = BitConverter.ToInt32(receivedBuffer, 4); int messageCode = BitConverter.ToInt32(receivedBuffer, 8); byte[] eventObjBytes = receivedBuffer.Skip(12).ToArray(); // 反序列化得到CustomEventArgs实例(需要你实现对应的反序列化方法) CustomEventArgs eventArgs = ParseBinaryToEvent(eventObjBytes); // 获取对应委托并触发事件 var targetHandler = EventHandlers[messageCode]; // 用空条件运算符避免委托为空时触发空引用异常 targetHandler?.Invoke(this, eventArgs); }
3. 验证字节数组解析的一致性
要确保接收端解析字节数组的顺序、偏移量和发送端完全匹配:发送端结构是sender(4字节) + receiver(4字节) + messageCode(4字节) + eventObj,所以接收端的偏移量必须是0、4、8,后续字节才是事件对象的序列化数据。另外注意BitConverter的字节序问题——如果发送端和接收端跨平台(比如Windows和Linux),需要用BitConverter.IsLittleEndian判断并统一字节序,否则会解析出错误的messageCode,导致调用错误的委托。
4. 确认Class A的订阅逻辑
Class A的订阅代码本身没问题,但要确保client.getHandler(111)返回的确实是Class B中EventHandlers[111]的委托实例(委托是引用类型,只要getHandler正确返回,订阅会直接关联到数组中的委托上)。
额外调试建议
- 在触发事件前添加日志,记录
messageCode和委托的订阅数量,方便确认是否有有效订阅者; - 测试序列化/反序列化逻辑,确保
CustomEventArgs能被正确还原; - 给
EventHandlers数组的访问加锁(如果是多线程场景),避免并发订阅/触发时出现异常。
内容的提问来源于stack exchange,提问作者de0x95

