You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 22:32:22