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

向集合添加对象新实例时出现疑似内存泄漏的异常问题

问题分析与解决建议

核心问题定位

你遇到的属性覆盖问题,大概率是多个HoloNETClient实例共享了同一个HoloNETDNA引用导致的。虽然你在方法里每次都new HoloNETDNA(),但如果HoloNETClient的构造函数没有对传入的HoloNETDNA做深拷贝,或者CurrentApp的属性是引用类型且存在复用逻辑,就会出现修改新实例的HoloNETDNA时,所有关联实例的属性被同步覆盖的情况。

另外,List<HoloNETClient>不是线程安全集合,如果是多线程环境下添加/操作实例,也可能出现引用混乱的意外情况。

具体解决步骤

1. 确保HoloNETDNA实例完全独立

修改CreateNewAppAgentClientConnection方法,直接在初始化HoloNETDNA时完成所有属性赋值,避免后续修改可能带来的引用问题;同时检查HoloNETClient构造函数,确认它对传入的HoloNETDNA进行了深拷贝(如果HoloNETDNA是引用类型):

private HoloNETClient CreateNewAppAgentClientConnection(ushort port)
{
    // 一次性初始化所有HoloNETDNA属性,避免后续赋值操作
    var dna = new HoloNETDNA()
    {
        HolochainConductorAppAgentURI = $"ws://127.0.0.1:{port}",
        AutoStartHolochainConductor = false,
        AutoShutdownHolochainConductor = false,
        AgentPubKey = CurrentApp.AgentPubKey,
        DnaHash = CurrentApp.DnaHash,
        InstalledAppId = CurrentApp.Name
    };

    var newClient = new HoloNETClient(dna);

    // 绑定事件处理
    newClient.OnConnected += _holoNETClientApp_OnConnected;
    newClient.OnReadyForZomeCalls += _holoNETClientApp_OnReadyForZomeCalls;
    newClient.OnZomeFunctionCallBack += _holoNETClientApp_OnZomeFunctionCallBack;
    newClient.OnDisconnected += _holoNETClientApp_OnDisconnected;
    newClient.OnDataReceived += _holoNETClientApp_OnDataReceived;
    newClient.OnDataSent += _holoNETClientApp_OnDataSent;
    newClient.OnError += _holoNETClientApp_OnError;

    return newClient;
}

如果HoloNETDNA内部包含引用类型属性,需要在HoloNETClient构造函数中对其进行深拷贝,比如给HoloNETDNA实现一个Clone()方法:

// 给HoloNETDNA类添加Clone方法
public class HoloNETDNA
{
    // ... 原有属性

    public HoloNETDNA Clone()
    {
        return new HoloNETDNA()
        {
            HolochainConductorAppAgentURI = this.HolochainConductorAppAgentURI,
            AutoStartHolochainConductor = this.AutoStartHolochainConductor,
            AutoShutdownHolochainConductor = this.AutoShutdownHolochainConductor,
            AgentPubKey = this.AgentPubKey, // 值类型直接复制,引用类型需递归拷贝
            DnaHash = this.DnaHash,
            InstalledAppId = this.InstalledAppId
        };
    }
}

// 修改HoloNETClient构造函数,使用拷贝后的实例
public HoloNETClient(HoloNETDNA dna)
{
    this.HoloNETDNA = dna.Clone();
}

2. 改用线程安全集合管理连接

替换List<HoloNETClient>为线程安全集合,比如ConcurrentDictionary<ushort, HoloNETClient>(通过端口号作为唯一键,方便快速查找和管理):

// 初始化线程安全集合,用端口号作为键
private ConcurrentDictionary<ushort, HoloNETClient> _holoNETappClients = new ConcurrentDictionary<ushort, HoloNETClient>();

// 添加实例时
var newClient = CreateNewAppAgentClientConnection(e.Port.Value);
newClient.Connect();
_holoNETappClients.TryAdd(e.Port.Value, newClient);

3. 验证实例独立性

添加实例后,打印每个HoloNETDNA的哈希码和属性值,确认每个实例的HoloNETDNA是独立对象:

newClient.Connect();
_holoNETappClients.TryAdd(e.Port.Value, newClient);

// 打印新实例信息
Console.WriteLine($"新增客户端:端口={e.Port.Value}, AgentPubKey={newClient.HoloNETDNA.AgentPubKey}, DNA哈希码={newClient.HoloNETDNA.GetHashCode()}");

// 遍历检查已有实例
foreach (var kvp in _holoNETappClients)
{
    var client = kvp.Value;
    Console.WriteLine($"已有客户端:端口={kvp.Key}, AgentPubKey={client.HoloNETDNA.AgentPubKey}, DNA哈希码={client.HoloNETDNA.GetHashCode()}");
}

如果所有HoloNETDNA的哈希码都不同,说明实例是独立的;如果有重复,证明存在引用共享问题,需要进一步排查HoloNETClient或HoloNETDNA的内部实现。

4. 优化连接池生命周期管理

  • 为每个客户端绑定断开事件,触发时自动从集合中移除:
    private void _holoNETClientApp_OnDisconnected(object sender, EventArgs e)
    {
        var client = sender as HoloNETClient;
        if (client != null)
        {
            // 从URI解析端口号作为键
            var port = ushort.Parse(client.HoloNETDNA.HolochainConductorAppAgentURI.Split(':').Last());
            _holoNETappClients.TryRemove(port, out _);
        }
    }
    
  • 定期清理无效连接:比如定时遍历集合,检查客户端的连接状态,移除已断开的实例。

内容的提问来源于stack exchange,提问作者David Ellams

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 12:32:34