ConcurrentDictionary - 破坏字典或坏代码?

时间:2012-01-05 22:06:32

标签: c# multithreading concurrency concurrentdictionary

好吧,所以我遇到了一个奇怪的小问题,坦白说我没有想法。我想把它扔出去看看我是否遗漏了一些我做错了,或者ConcurrentDictionary无法正常工作的东西。这是代码:

(Cache是​​一个包含静态ConcurrentDictionary键的类)

var tmp = Cache.Keys.GetOrAdd(type,
                key =>
                {
                    var keys = context.GetKeys(key);
                    if (keys.Count() == 1)
                    {
                        return new KeyInfo
                            {
                                Name = keys.First().Name,
                                Info = key.GetInfo(keys.First().Name)
                            };
                    }

                    return null;
                });

            if (tmp == null)
                Cache.Keys.TryRemove(type, out tmp);

            return tmp;

问题是偶尔tmpnull,导致TryRemove行运行,但上面的return null;行永远不会被点击。由于return nullnull唯一将tmp放入字典并且永远不会运行,null怎么可能public class Cache { public static ConcurrentDictionary<Type, Info> Keys = new ConcurrentDictionary<Type, Info>(); public static ConcurrentDictionary<Type, string> SetNames = new ConcurrentDictionary<Type, string>(); }


包含Cache类(此代码不使用SetNames):

{{1}}

2 个答案:

答案 0 :(得分:3)

如果您从tmp返回单个项目以外的任何内容,则

context.GetKeys(key)可以为null。在这种情况下,keys.Count() != 1和空项将插入到Cache.Keys中,用于指定的键(并从GetOrAdd返回,并分配给tmp)。

编辑:想到另一种可能性。什么数据类型是关键?它是某种定制类吗?它看起来像是。如果是,您是否正确实施了EqualsGetHashcode

答案 1 :(得分:0)

我应该暂时关闭它,但我完全忘了它。由于TryRemove,该示例不是线程安全的,但仅用于调试目的。我最后通过重写来解决这个问题,所以也许有些代码的某些评论是陈旧的是正确的。但是,代码不再存在以确认。

我正在将此问题归咎于用户错误(当然是我自己的)。谢谢大家的时间!