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

.NET 6中SortedSet添加已确认唯一的元素时随机失败的问题排查求助

.NET 6中SortedSet添加已确认唯一的元素时随机失败的问题排查求助

各位大佬好,我最近在维护一个.NET 6应用时,碰到了SortedSet<T>的一个诡异问题——明明要添加的元素都是唯一的,但有时候就是会有元素加不进去,触发我的警告日志。折腾了好几天都没找到根源,想请大家帮忙分析下。

问题场景与核心代码

我封装了一个批量添加元素到SortedSet的方法,代码如下(锁对象是全局唯一的,所有访问这个SortedSet的方法都会用它加锁):

private readonly SortedSet<T> sortedSet = new();
private readonly object lockObj = new();

public void AddRange(IEnumerable<T> items)
{
    lock (lockObj)
    {
        var count = items.Count();
        var added = 0;
        foreach (var item in items)
        {
            if (sortedSet.Add(item))
                added++;
        }
        if (added != count)
        {
            logger.Warning("预期添加{Count}个元素,实际仅添加{Added}个", count, added);
        }
    }
}

这段代码会随机触发警告:实际添加的元素数量比传入的总数少1个,但我完全找不到原因。

已完成的排查步骤

  1. 验证待添加元素的唯一性:我在锁内部加了一段调试代码,用HashSet<T>确认传入的items没有重复:

    var debugSet = new HashSet<T>();
    debugSet.UnionWith(items);
    logger.Information("传入{count}个元素,其中{unique}个是唯一的", items.Count(), debugSet.Count);
    

    日志显示每次传入的元素数量和HashSet的计数完全一致,说明所有待添加元素都是唯一的。

  2. 确认并发访问安全:我逐一检查了所有操作这个SortedSet的方法——不管是添加、删除还是查询,全部都用了同一个lockObj加锁,按道理不会出现并发修改的问题。

  3. 元素类型的细节:这里的T是一个记录类型ScheduledAutoload,定义如下:

    public record ScheduledAutoload : IScheduled, IComparable<IScheduled>
    {
        public ScheduledAutoload(Guid id, DateTime scheduledTime)
        {
            Id = id;
            ScheduledTime = scheduledTime;
        }
    
        public Guid Id { get; init; } // 每个实例都有唯一的Id
        public DateTime ScheduledTime { get; init; }
        // 其他几个init-only属性
    
        public int CompareTo(IScheduled obj)
        {
            return ScheduledTime.CompareTo(obj.ScheduledTime);
        }
    }
    

    这是个record类型,默认的相等性判断基于所有属性,而且我也通过HashSet验证了实例是唯一的。不过我自定义了CompareTo方法,让SortedSet按ScheduledTime排序。

我的核心疑问

现在我实在搞不懂:

  • 锁已经确保了SortedSet的访问是单线程的,为什么还会出现元素加不进去的情况?
  • 明明HashSet都确认元素是唯一的,为什么SortedSet.Add()会返回false?
  • 会不会是自定义的CompareTo方法导致SortedSet的相等判断逻辑和HashSet不一致?

我知道用SortedSet.UnionWith()可能会更高效,但我现在想先搞清楚这个问题的根源,再做代码优化。有没有大佬遇到过类似的情况,或者能帮我分析下可能的原因?

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 09:03:10