线程安全字典...关键值对不可数? (。净)

时间:2009-03-10 18:36:06

标签: c# dictionary

我正在阅读(考虑编写我自己的线程安全字典)我找到了以下实现。

http://devplanet.com/blogs/brianr/archive/2008/09/26/thread-safe-dictionary-in-net.aspx

一般看起来很不错,但有一件事让我感到困惑。

以下内容: 无法枚举线程安全字典。相反,枚举键或值集合

可以在

中找到
public virtual IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
    throw new NotSupportedException("Cannot enumerate a threadsafe dictionary.  Instead, enumerate the keys or values collection");
}


IEnumerator IEnumerable.GetEnumerator()
{
    throw new NotSupportedException("Cannot enumerate a threadsafe dictionary.  Instead, enumerate the keys or values collection");
}

我没有得到的是为什么可以枚举键或值,而不是字典的kvp?

有人可以为我阐明这一点吗?提前谢谢。

3 个答案:

答案 0 :(得分:4)

SO用户和MS员工JaredPar在他的博客上有一个关于构建线程安全集合的简短系列,绝对值得您花时间:

<强> [更新:]
再读一遍,如果你的时间不够,那么第二篇文章可能就是它自己的。

总结一下:您发现在线发布的大多数“线程安全”集合通常要么不是非常有用,要么一次只有线程安全的一个操作,使“{1}}或.Count等”决策“成员无用(到下一行代码运行时,它们“陈旧”。

答案 1 :(得分:2)

我可以直接回答这个问题,因为我写了那本字典:)

在字典上获取枚举器将获得对内部KVP集的引用。你必须保持读锁定,直到你完成枚举,这可能需要很长时间。

我说要枚举键或值的原因是我在请求时复制键和值列表,因此我没有返回对词典内部列表的引用,如果你改变了锁定,可能会导致问题。虽然,我想你也可以在KVP上实现相同的模式,因为它们是只读的。

    public virtual ICollection<TKey> Keys
    {
        get
        {
            using (new ReadOnlyLock(this.dictionaryLock))
            {
                return new List<TKey>(this.dict.Keys);
            }
        }
    }

    public virtual ICollection<TValue> Values
    {
        get
        {
            using (new ReadOnlyLock(this.dictionaryLock))
            {
                return new List<TValue>(this.dict.Values);
            }
        }
    }

答案 2 :(得分:1)

当您枚举KVP集合时,您正在进入和退出整个字典的锁定。因此,在枚举的循环体中,您不在锁中,并且更改KVP可能会导致竞争条件。