使用NetworkCallbackDelegate时出现NullReferenceException问题求助
问题描述
在C#开发的FiveM脚本中,通过事件从数据库获取玩家信息时触发System.NullReferenceException错误。已确认数据库连接正常、变量类型匹配,且回调传递的三个参数均非空,现提供相关代码与错误日志,寻求解决办法。
错误日志
[ 9419687] [b2699_GTAProce] MainThrd/ System.NullReferenceException: Object reference not set to an instance of an object. [ 9419687] [b2699_GTAProce] MainThrd/ [ 9419687] [b2699_GTAProce] MainThrd/ [ 9419687] [b2699_GTAProce] MainThrd/ Server stack trace: [ 9419687] [b2699_GTAProce] MainThrd/ at CitizenFX.Core.InternalManager.PrintError (System.String where, System.Exception what) [0x00081] in C:\gl\builds\master\fivem\code\client\clrcore\InternalManager.cs:595 [ 9419687] [b2699_GTAProce] MainThrd/ at CitizenFX.Core.InternalManager.CallRef (System.Int32 refIndex, System.Byte[] argsSerialized, System.IntPtr& retvalSerialized, System.Int32& retvalSize) [0x000b6] in C:\gl\builds\master\fivem\code\client\clrcore\InternalManager.cs:527 [ 9419687] [b2699_GTAProce] MainThrd/ at (wrapper remoting-invoke-with-check) CitizenFX.Core.InternalManager:CallRef (int,byte[],intptr&,int&) [ 9419687] [b2699_GTAProce] MainThrd/ at (wrapper xdomain-dispatch) CitizenFX.Core.InternalManager:CallRef (object,byte[]&,byte[]&,int,byte[],int&) [ 9419687] [b2699_GTAProce] MainThrd/ [ 9419687] [b2699_GTAProce] MainThrd/ Exception rethrown at [0]: [ 9419687] [b2699_GTAProce] MainThrd/ at (wrapper xdomain-invoke) CitizenFX.Core.InternalManager:CallRef (int,byte[],intptr&,int&) [ 9419687] [b2699_GTAProce] MainThrd/ at (wrapper remoting-invoke-with-check) CitizenFX.Core.InternalManager:CallRef (int,byte[],intptr&,int&) [ 9419687] [b2699_GTAProce] MainThrd/ at CitizenFX.Core.MonoScriptRuntime.CallRef (System.Int32 refIndex, System.Byte[] argsSerialized, System.Int32 argsSize, System.IntPtr& retvalSerialized, System.Int32& retvalSize) [0x00013] in C:\gl\builds\master\fivem\code\client\clrcore\MonoScriptRuntime.cs:228
客户端代码
public void GetPlayerInformations() { TriggerServerEvent("MST_SV_GetInformationOfPlayer",new Action <string, int, string>((userId, department, callsign) => { _Functions.SendTextToConsole(Functions.InfoType.Debug, $"UserId: {userId} | Department: {department} | Callsign: {callsign}"); if (userId != null) { UserId = userId; Department = department; Callsign = callsign; } })); }
服务端代码
private static void GetInformationOfPlayer([FromSource] Player player, NetworkCallbackDelegate callback) { try { using (MySqlConnection connection = Database.GetConnection()) { using (MySqlCommand command = connection.GetCommand()) { command.CommandText = "select * from user where license = @identifier"; command.Parameters.AddWithValue("@identifier", player.Identifiers["license"]); using (DbDataReader result = command.ExecuteReader()) { if (result.Read()) { _functions.SendTextToConsole(Functions.InfoType.Debug,$"License : {result["license"]}, Department : {result["department"]}, Callsign : {result["callsign"]}."); callback.Invoke(Convert.ToString(result["license"]), Convert.ToInt32(result["department"]), Convert.ToString(result["callsign"])); _functions.SendTextToConsole(Functions.InfoType.Info, $"Informations of player {player.Name} has been loaded successfully."); result.Close(); } else { // 与当前问题无关的其他脚本部分 } } } } } catch (Exception e) { _functions.SendTextToConsole(Functions.InfoType.Error, $"An error has occurred while loading informations of player {player.Name} : {e.Message}"); } }
问题排查与解决办法
对齐回调委托签名
服务端使用的NetworkCallbackDelegate需与客户端传递的Action<string, int, string>签名完全匹配。建议显式定义一致的委托类型,避免隐式转换导致的空引用:public delegate void PlayerInfoCallback(string userId, int department, string callsign);之后将服务端方法参数改为
PlayerInfoCallback callback。校验玩家License标识符
服务端中player.Identifiers["license"]可能不存在或为空,在执行SQL前添加判断:if (!player.Identifiers.TryGetValue("license", out string license) || string.IsNullOrEmpty(license)) { _functions.SendTextToConsole(Functions.InfoType.Error, $"玩家 {player.Name} 无有效License标识符"); callback.Invoke(null, 0, null); return; } command.Parameters.AddWithValue("@identifier", license);处理数据库字段空值
数据库字段可能为DBNull,直接转换会引发异常,需先判断:string userId = result["license"] != DBNull.Value ? Convert.ToString(result["license"]) : null; int department = result["department"] != DBNull.Value ? Convert.ToInt32(result["department"]) : 0; string callsign = result["callsign"] != DBNull.Value ? Convert.ToString(result["callsign"]) : null; callback.Invoke(userId, department, callsign);检查日志工具实例
客户端_Functions和服务端_functions需确保已初始化,避免调用SendTextToConsole时触发空引用。处理FiveM线程安全问题
客户端回调若涉及游戏对象操作,需调度到主线程执行:MainThreadScheduler.Instance.Enqueue(() => { UserId = userId; Department = department; Callsign = callsign; });
内容的提问来源于stack exchange,提问作者Dylan Pageot
相关产品推荐
相关产品推荐

