昨天我发现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”(位于 ....)
未将对象引用设置到对象的实例。
ConcurrentDictionary 线程安全 不代表它存储的对象也是线程安全的。
存储的对象也是线程安全的
这个是啥意思?能举个例子说详细点吗?
@小草上飞飞:
有两点吧,以你上面的为例。
线程安全的资源变成了非线程安全的资源,多线程操作非线程安全的资源自然就会出现空引用的情况,对象X在A线程中已经disposed掉了,B线程不知道情况下继续操作对象X
这个ToArray会保存一个当时的快照啊,我昨天靠ToArray解决了值不能为null的问题,现在偶尔出现这个空指针的问题。
@小草上飞飞: ADS_B.Tracks.GlobalInstance.TrackList.ToArray() 这是非线程安全资源, understand?
@~扎克伯格: 但是这个Array只有这个方法在用,其他方法不用,没有多线程操作一个Array的情况,难道是我toArray之后,这个ConcurrentDictionary就变成Array了?多线程这块搞不清楚
这种操作慎用,严重降低ConcurrentDictionary的性能。