最大的問題是:你需要foreach
是一個快照嗎?
如果答案是「否」,那麼使用ConcurrentDictionary
,你可能會沒事的。 (剩下的一個問題是插入和讀取的性質是否以不好的方式擊中了條紋鎖,但是如果是這種情況,您會發現正常的讀取和寫入字典的情況更糟)。
但是,因爲它的GetEnumerator
沒有提供快照,所以它不會在開始處列舉與末尾相同的開始。它可能會遺漏物品或重複物品。問題是這對你是否是一場災難。
如果如果您有重複項而不是其他項,那麼您可以用Distinct()
(無論按鍵或按鍵和值都按要求)過濾出重複項。
如果你真的需要它是一個硬快照,那麼採取以下方法。
有ConcurrentDictionary
(dict
)和ReaderWriterLockSlim
(rwls
)。在讀取和寫入獲得讀鎖(是的,即使你寫):
public static void AddToDict(string key, string value)
{
rwls.EnterReadLock();
try
{
dict[key] = value;
}
finally
{
rwls.ExitReadLock();
}
}
public static bool ReadFromDict(string key, out string value)
{
rwls.EnterReadLock();
try
{
return dict.TryGetValue(key, out value);
}
finally
{
rwls.ExitReadLock();
}
}
現在,當我們想枚舉字典,我們獲取寫入鎖定(即使我們正在閱讀):
public IEnumerable<KeyValuePair<string, string>> EnumerateDict()
{
rwls.EnterWriteLock();
try
{
return dict.ToList();
}
finally
{
rwls.ExitWriteLock();
}
}
這種方式,我們獲得了讀寫共享鎖,因爲與參與,對於我們的矛盾ConcurrentDictionary
交易。我們獲得枚舉的排他鎖,但時間足夠長以在列表中獲得字典的快照,然後該列表僅在該線程中使用,並且不與其他任何其他人共享。
你必須小心OP所需的'foreach',因爲它不是一個快照,它可能是'ConcurrentDictionary'上的'foreach'的bug,除非你可以在工作時改變它它,或者自己添加快照。 –