base.EndInvoke("", _args, result) not find

本文探讨了在编程中遇到的连续累加记录问题,并解释了如何通过实例化解决此问题,确保数据正确保存。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  public string EndUpdateStoreBusinessDateRecord(System.IAsyncResult result)

{
       object[] _args = new object[0];
        string _result = ((string)(base.EndInvoke("UpdateStoreBusinessDateRecord", _args, result)));
        return _result;

}

 

this.storeBizDateRecords = new ObservableCollection<StoreBusinessDateRecord>();

找了半天原来save后没实例化,导致连续累加记录;

using BaseServer.Core; using BaseServer.Kernel; using Common.Logging; using SuperSocket.SocketBase; using SuperSocket.SocketBase.Protocol; using System; using LuckdrawServer.Core; using Wisher.Basic.Log; using BaseServer.Util; using LuckdrawServer.Setting; namespace GameServer.Core { /// <summary> /// 协议格式如下: /// +---+-------------------------------+ /// | l | | /// | e | request body | /// | n | | /// |(4)| | /// +---+-------------------------------+ /// len: 数据包大小 /// request body: 包体 /// </summary> public class PlayerAppServer : AppServer<PlayerSession, BaseRequestInfo> { private MessageProcesserFacade messageProcesserFacade; private MessageProcesser messageProcesser; public PlayerAppServer() : base(new DefaultReceiveFilterFactory<ChessCardReceiveFilter, BaseRequestInfo>()) { try { //Logger.Info("服务器启动"); this.messageProcesserFacade = new MessageProcesserFacade(); //IApplicationContext applicationContext = ContextRegistry.GetContext(); //PlatformNotifier platformNotifier = applicationContext.GetObject("platformNotifier") as PlatformNotifier; messageProcesser = new MessageProcesser(); this.messageProcesserFacade.Initialize(messageProcesser); } catch (Exception ex) { MyLog.Error(typeof(PlayerAppServer), ex.Message); } } // override AppServer public override bool Start() { LogManager.GetLogger<PlayerAppServer>().Info("Start"); MyLog.Info(typeof(PlayerAppServer), "Start()"); SprotoBufCodec.Init(Protocol.Instance.Protocol, SprotoType.Protocol.Instance.Protocol); this.NewRequestReceived += PlayerAppServer_NewRequestReceived; this.SessionClosed += PlayerAppServer_SessionClosed; return base.Start(); } void PlayerAppServer_SessionClosed(PlayerSession session, CloseReason value) { MyLog.Info(typeof(PlayerAppServer), value.ToString()); this.messageProcesserFacade.HandlePlayerOffline(session.PlayerID, session.BakPlayerID, session.RoomID); } // override AppServer public override void Stop() { MyLog.Info(typeof(PlayerAppServer), "Stop()"); base.Stop(); } // override AppServerBase protected override void OnStarted() { MyLog.Info(typeof(PlayerAppServer), "OnStarted()"); base.OnStarted(); } // override AppServerBase protected override void OnStopped() { try { //IApplicationContext applicationContext = ContextRegistry.GetContext(); //PlatformNotifier platformNotifier = applicationContext.GetObject("platformNotifier") as PlatformNotifier; //RoomConfig roomConfig = applicationContext.GetObject("roomConfig") as RoomConfig; //PlatformNotifier.GameServerStateService.Offline(roomConfig.GameId, roomConfig.RoomId); //DataHubService messageProcesser.Stop(); MyLog.Info(typeof(PlayerAppServer), "OnStopped()"); } catch (Exception ex) { Logger.Error(ex); MyLog.Error(typeof(PlayerAppServer), ex.Message); } base.OnStopped(); } // override AppServerBase protected override void OnNewSessionConnected(PlayerSession session) { base.OnNewSessionConnected(session); } /// <summary> /// 收到协议处理 /// </summary> /// <param name="session"></param> /// <param name="requestInfo"></param> void PlayerAppServer_NewRequestReceived(PlayerSession session, BaseRequestInfo requestInfo) { try { int type = int.Parse(requestInfo.Key); if (!AbsSettingGame.GetInstance().IsIgnoreLog(type)) MyLog.Info(typeof(PlayerAppServer), string.Format("NewRequestReceived()session:{0},requestInfo:{1},type:{2}", session, requestInfo, type)); this.messageProcesserFacade.ProcessMessage(session, requestInfo.MessageHead, requestInfo.Body); } catch (Exception ex) { Logger.Error(ex); MyLog.Error(typeof(PlayerAppServer), ex.ToString()); } } } } 问题提示2025-07-20 14:58:15,193 [9188] ERROR GameServer - System.ArgumentNullException: 值不能为 null。 参数名: key Server stack trace: 在 System.Collections.Concurrent.ConcurrentDictionary`2.TryRemove(TKey key, TValue& value)BaseServer.Core.MessageHandler.TryRemove(String playerId)BaseServer.Room.RoomMgr.PlayerOfflineHandler(IClientSession session)BaseServer.Core.BaseMessageProcesser.HandlePlayerOffline(IClientSession session)BaseServer.Core.MessageProcesserFacade.HandlePlayerOffline(IClientSession session) 在 GameServer.Core.PlayerAppServer.PlayerAppServer_SessionClosed(ClientSession session, CloseReason value) 位置 d:\外网\Server\GameServer\SHZServer\GameServer\Core\PlayerAppServer.cs:行号 65 在 System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr md, Object[] args, Object server, Object[]& outArgs) 在 System.Runtime.Remoting.Messaging.StackBuilderSink.AsyncProcessMessage(IMessage msg, IMessageSink replySink) Exception rethrown at [0]: 在 System.Runtime.Remoting.Proxies.RealProxy.EndInvokeHelper(Message reqMsg, Boolean bProxyCase) 在 System.Runtime.Remoting.Proxies.RemotingProxy.Invoke(Object NotUsed, MessageData& msgData) 在 SuperSocket.SocketBase.SessionHandler`2.EndInvoke(IAsyncResult result) 在 SuperSocket.SocketBase.AppServerBase`2.OnSessionClosedCallback(IAsyncResult result)
最新发布
07-21
<think>我们正在处理一个C#服务器应用程序中的异常,具体是在SessionClosed事件中发生了ArgumentNullException,参数名为"key"。 这个异常通常发生在尝试使用一个null值作为字典(Dictionary)的键(key)时。因为字典不允许键为null。 可能的原因: 1. 在SessionClosed事件处理程序中,我们可能尝试从一个字典中通过某个键获取值,但传入的键是null。 2. 或者我们尝试添加一个键为null的项到字典中。 由于错误信息明确指出参数是"key",因此问题很可能是在字典操作时使用了null作为键。 解决思路: 1. 检查SessionClosed事件处理程序中的代码,特别是所有使用字典(Dictionary)的地方。 2. 确保在访问字典之前,键不为null。 3. 如果键可能为null,则需要进行空值检查,避免使用null键。 步骤: 1. 定位到触发SessionClosed事件的代码位置。 2. 检查该事件处理程序中所有使用字典的地方(例如:查找、添加、删除等操作)。 3. 在访问字典前,对键进行非空检查。 示例代码可能出现的问题: 假设有如下代码: ```csharp private void SessionClosed(object sender, SessionEventArgs e) { string sessionKey = GetSessionKey(e.Session); // 可能返回null _sessionDictionary.Remove(sessionKey); // 如果sessionKey为null,则会抛出ArgumentNullException } ``` 修正方法: 在操作字典之前检查键是否为null。 ```csharp private void SessionClosed(object sender, SessionEventArgs e) { string sessionKey = GetSessionKey(e.Session); if (sessionKey != null) { _sessionDictionary.Remove(sessionKey); } else { // 处理sessionKey为null的情况,例如记录日志等 } } ``` 另一种可能:我们可能使用了Session的某个属性作为键,而这个属性在会话关闭时可能已经被置为null。因此,我们需要确保使用的键是可靠的。 如果问题仍然存在,我们需要检查整个会话生命周期,确保在会话关闭时,我们用来生成键的数据仍然有效。 此外,还应该考虑线程安全问题。如果多个线程同时操作同一个字典,而字典不是线程安全的,也可能导致异常。但这里异常明确是ArgumentNullException,所以首先考虑键为null的情况。 如果代码中使用了多个字典,需要逐一排查。 建议: 1. 在代码中添加日志记录,记录在SessionClosed事件中使用的键的值,特别是在进行字典操作之前。 2. 使用调试器,在SessionClosed事件发生时设置断点,检查键的值。 如果问题难以定位,可以考虑使用更安全的数据结构,例如使用`ConcurrentDictionary`(如果涉及多线程)并在操作前检查键的合法性。 但是,请注意,`ConcurrentDictionary`的Remove方法同样不允许null键,因此仍然需要检查。 因此,关键还是在于避免使用null作为键。 总结:解决方案是在使用键之前进行非空检查,并处理可能出现的null情况。 相关问题: 1. 如何在C#中安全地操作字典以避免空键异常? 2. 在会话关闭事件中,如何确保操作的数据有效性? 3. 如何调试C#中的ArgumentNullException异常?</think>### 解决方案:解决SessionClosed事件中的ArgumentNullException异常 该异常通常发生在尝试使用`null`值作为字典键时。以下是逐步解决方案: #### 1. **定位问题代码** 在`SessionClosed`事件处理程序中,检查所有字典操作(如`Add`、`Remove`、`ContainsKey`等),特别是使用`Session`属性作为键的代码: ```csharp // 错误示例:session.ID 可能为 null _sessionCache.Remove(session.ID); // 引发 ArgumentNullException ``` #### 2. **添加空值检查** 在操作字典前显式检查键值: ```csharp private void OnSessionClosed(object sender, SessionEventArgs e) { if (e.Session?.ID != null) // 关键检查 { _sessionCache.Remove(e.Session.ID); } else { // 记录警告日志 Logger.Warn($"Session closed with null ID: {e.Session}"); } } ``` #### 3. **验证会话生命周期** 确保会话对象在关闭前未被意外释放: ```csharp // 在会话初始化时确保ID不为空 public void InitializeSession(Session session) { session.ID = GenerateSessionId(); // 确保ID生成逻辑可靠 _sessionCache.TryAdd(session.ID, session); } ``` #### 4. **使用线程安全字典** 若涉及多线程,改用`ConcurrentDictionary`: ```csharp private readonly ConcurrentDictionary<string, Session> _sessionCache = new ConcurrentDictionary<string, Session>(); // 安全移除 _sessionCache.TryRemove(session.ID, out _); // 自动处理空键 ``` #### 5. **防御性日志记录** 添加详细日志定位空值来源: ```csharp private void OnSessionClosed(object sender, SessionEventArgs e) { if (e.Session == null) { Logger.Error("SessionClosed event received null session"); return; } // ...其他逻辑 } ``` ### 根本原因分析 此异常通常由以下情况触发: 1. **会话提前释放**:会话对象在关闭前被意外置空 2. **异步操作竞争**:关闭事件触发时,会话ID尚未初始化完成 3. **脏会话状态**:网络断开等异常导致会话信息不完整 > **最佳实践**:在访问任何字典键前,始终验证键值有效性。会话ID建议使用`Guid.NewGuid().ToString()`生成以保证非空[^1]。 --- ### 相关问题 1. 如何避免C#字典操作中的`KeyNotFoundException`? 2. `ConcurrentDictionary`与普通字典在并发场景下的性能差异? 3. 在分布式系统中如何安全管理会话生命周期? [^1]: 引用自C#官方文档:当使用字典集合时,键值必须为非空引用,否则会引发`ArgumentNullException`。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值