首页新闻找找看学习计划

关于 ConcurrentDictionary 遍历问题

0
悬赏园豆:50 [已解决问题] 解决于 2020-06-15 14:17

昨天我发现ConcurrentDictionary.ToArray()方法很好用,今天我就发现在遍历的时候出了问题,淦!

        public static Track GetTrack(string callSign)
        {
            if (ADS_B.Tracks.GlobalInstance.TrackList.Count !=0)
            {
                foreach (var pair in ADS_B.Tracks.GlobalInstance.TrackList.ToArray())
                {
                    if (pair.Value.Identification.Equals(callSign) || pair.Value.Identification == callSign)
                    {
                        return pair.Value;
                    }
                }
            }
                return null;
        }

错误:

引发的异常:“System.NullReferenceException”(位于 ....)
未将对象引用设置到对象的实例。

< >
分享
最佳答案
0

ConcurrentDictionary 线程安全 不代表它存储的对象也是线程安全的。

收获园豆:25
xiaogui340 | 菜鸟二级 |园豆:469 | 2020-05-28 17:43

存储的对象也是线程安全的

小草上飞飞 | 园豆:156 (初学一级) | 2020-05-28 18:56

这个是啥意思?能举个例子说详细点吗?

小草上飞飞 | 园豆:156 (初学一级) | 2020-05-28 18:56

@小草上飞飞:
有两点吧,以你上面的为例。

  1. ConcurrentDictionary 本身对 对象的存取 提供了线程安全的方法,但是 遍历貌似不是线程安全的
  2. ConcurrentDictionary.ToArray()作了一个浅copy来遍历,但如果另外一个线程对ConcurrentDictionary的内部对象释放了资源,那么你遍历中获取到的该对象就不是一个有效的对象
xiaogui340 | 园豆:469 (菜鸟二级) | 2020-05-28 19:58
其他回答(2)
0

线程安全的资源变成了非线程安全的资源,多线程操作非线程安全的资源自然就会出现空引用的情况,对象X在A线程中已经disposed掉了,B线程不知道情况下继续操作对象X

收获园豆:25
~扎克伯格 | 园豆:1837 (小虾三级) | 2020-05-21 10:52

这个ToArray会保存一个当时的快照啊,我昨天靠ToArray解决了值不能为null的问题,现在偶尔出现这个空指针的问题。

支持(0) 反对(0) 小草上飞飞 | 园豆:156 (初学一级) | 2020-05-21 11:00

@小草上飞飞: ADS_B.Tracks.GlobalInstance.TrackList.ToArray() 这是非线程安全资源, understand?

支持(0) 反对(0) ~扎克伯格 | 园豆:1837 (小虾三级) | 2020-05-21 11:19

@~扎克伯格: 但是这个Array只有这个方法在用,其他方法不用,没有多线程操作一个Array的情况,难道是我toArray之后,这个ConcurrentDictionary就变成Array了?多线程这块搞不清楚

支持(0) 反对(0) 小草上飞飞 | 园豆:156 (初学一级) | 2020-05-27 10:04
0

这种操作慎用,严重降低ConcurrentDictionary的性能。

balahoho | 园豆:2096 (老鸟四级) | 2020-05-21 13:45
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册