线程安全的SortedDictionary

我创建了一个使用SortedDictionary来存储和操作数据的类。 除非在multithreading环境中实现,否则该类很有效。 现在,我想通过为内部SortedDictionary类编写包装类来使类线程安全。 我想使用Reader-Writer Locks来实现它,但是现在,我在编写包装器本身时遇到了问题。 具体来说,我不确定如何为字典实现Enumerator 。 这是我现在的完整代码。

  public class ConcurrentSortedDictionary : IEnumerable<KeyValuePair> { #region Variables SortedDictionary _dict; #endregion #region Constructors public ConcurrentSortedDictionary() { _dict = new SortedDictionary(); } public ConcurrentSortedDictionary(IComparer comparer) { _dict = new SortedDictionary(comparer); } public ConcurrentSortedDictionary(IDictionary dictionary) { _dict = new SortedDictionary(dictionary); } public ConcurrentSortedDictionary(IDictionary dictionary, IComparer comparer) { _dict = new SortedDictionary(dictionary, comparer); } #endregion #region Properties public IComparer Comparer { get { return _dict.Comparer; } } public int Count { get { return _dict.Count; } } public TValue this[TKey key] { get { return _dict[key]; } set { _dict[key] = value; } } public SortedDictionary.KeyCollection Keys { get { return new SortedDictionary.KeyCollection(_dict); } } public SortedDictionary.ValueCollection Values { get { return new SortedDictionary.ValueCollection(_dict); } } #endregion #region Methods public void Add(TKey key, TValue value) { _dict.Add(key, value); } public void Clear() { _dict.Clear(); } public bool ContainsKey(TKey key) { return _dict.ContainsKey(key); } public bool ContainsValue(TValue value) { return _dict.ContainsValue(value); } public void CopyTo(KeyValuePair[] array, int index) { _dict.CopyTo(array, index); } public override bool Equals(Object obj) { return _dict.Equals(obj); } IEnumerator<KeyValuePair> IEnumerable<KeyValuePair>.GetEnumerator() { return GetEnumerator(); } public IEnumerator<KeyValuePair> GetEnumerator() { return _dict.GetEnumerator(); } public override int GetHashCode() { return _dict.GetHashCode(); } public bool Remove(TKey key) { return _dict.Remove(key); } public override string ToString() { return _dict.ToString(); } public bool TryGetValue(TKey key, out TValue value) { return _dict.TryGetValue(key, out value); } #endregion } 

当我编译代码时,我收到错误消息:

‘ConcurrentSortedDictionary’没有实现接口成员’System.Collections.IEnumerable.GetEnumerator()’。 ‘ConcurrentSortedDictionary.GetEnumerator()’无法实现’System.Collections.IEnumerable.GetEnumerator()’,因为它没有匹配的返回类型’System.Collections.IEnumerator’。

我看了几篇与此有关的post作为参考:

如何在我的实现IEnumerable 的Dictionary包装器类中实现IEnumerable? 实现线程安全字典的最佳方法是什么?

但我不明白我做错了什么。 非常感谢任何帮助。

问题出在这里:

 IEnumerator> IEnumerable>.GetEnumerator() { return GetEnumerator(); } public IEnumerator> GetEnumerator() { return _dict.GetEnumerator(); } 

你需要:

 public IEnumerator> GetEnumerator() { return _dict.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return _dict.GetEnumerator(); } 

第二个非genericsGetEnumerator()是一个显式接口实现 ,并且需要作为C#中存在generics和generics集合之前的不幸回归。

另请参见: IEnumerable 提供了两个GetEnumerator方法 – 它们之间有什么区别? (特别是Michael B的回答 )。

但是,如果您希望枚举与类的其余部分一起是线程安全的,您可能还需要编写自己的线程安全的IEnumerator类型,它与您的类中的读取器/写入器锁相配合!

在实施了dvnrrs的建议之后,我现在让这个class级运作良好。 我甚至为IEnumerable接口添加了一个包装器类,以保护SortedDictionary的枚举(此示例中修改的代码如下: http : //www.codeproject.com/Articles/56575/Thread-safe-enumeration-in-C )。 以下是包含Reader-Writer Locks的更新代码:

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections; using System.Threading; public class SafeEnumerator : IEnumerator { #region Variables // this is the (thread-unsafe) // enumerator of the underlying collection private readonly IEnumerator _enumerator; // this is the object we shall lock on. private ReaderWriterLockSlim _lock; #endregion #region Constructor public SafeEnumerator(IEnumerator inner, ReaderWriterLockSlim readWriteLock) { _enumerator = inner; _lock = readWriteLock; // Enter lock in constructor _lock.EnterReadLock(); } #endregion #region Implementation of IDisposable public void Dispose() { // .. and exiting lock on Dispose() // This will be called when the foreach loop finishes _lock.ExitReadLock(); } #endregion #region Implementation of IEnumerator // we just delegate actual implementation // to the inner enumerator, that actually iterates // over some collection public bool MoveNext() { return _enumerator.MoveNext(); } public void Reset() { _enumerator.Reset(); } public T Current { get { return _enumerator.Current; } } object IEnumerator.Current { get { return Current; } } #endregion } public class ConcurrentSortedDictionary : IEnumerable> { #region Variables private ReaderWriterLockSlim _readWriteLock = new ReaderWriterLockSlim(); SortedDictionary _dict; #endregion #region Constructors public ConcurrentSortedDictionary() { _dict = new SortedDictionary(); } public ConcurrentSortedDictionary(IComparer comparer) { _dict = new SortedDictionary(comparer); } public ConcurrentSortedDictionary(IDictionary dictionary) { _dict = new SortedDictionary(dictionary); } public ConcurrentSortedDictionary(IDictionary dictionary, IComparer comparer) { _dict = new SortedDictionary(dictionary, comparer); } #endregion #region Properties public IComparer Comparer { get { _readWriteLock.EnterReadLock(); try { return _dict.Comparer; } finally { _readWriteLock.ExitReadLock(); } } } public int Count { get { _readWriteLock.EnterReadLock(); try { return _dict.Count; } finally { _readWriteLock.ExitReadLock(); } } } public TValue this[TKey key] { get { _readWriteLock.EnterReadLock(); try { return _dict[key]; } finally { _readWriteLock.ExitReadLock(); } } set { _readWriteLock.EnterWriteLock(); try { _dict[key] = value; } finally { _readWriteLock.ExitWriteLock(); } } } public SortedDictionary.KeyCollection Keys { get { _readWriteLock.EnterReadLock(); try { return new SortedDictionary.KeyCollection(_dict); } finally { _readWriteLock.ExitReadLock(); } } } public SortedDictionary.ValueCollection Values { get { _readWriteLock.EnterReadLock(); try { return new SortedDictionary.ValueCollection(_dict); } finally { _readWriteLock.ExitReadLock(); } } } #endregion #region Methods public void Add(TKey key, TValue value) { _readWriteLock.EnterWriteLock(); try { _dict.Add(key, value); } finally { _readWriteLock.ExitWriteLock(); } } public void Clear() { _readWriteLock.EnterWriteLock(); try { _dict.Clear(); } finally { _readWriteLock.ExitWriteLock(); } } public bool ContainsKey(TKey key) { _readWriteLock.EnterReadLock(); try { return _dict.ContainsKey(key); } finally { _readWriteLock.ExitReadLock(); } } public bool ContainsValue(TValue value) { _readWriteLock.EnterReadLock(); try { return _dict.ContainsValue(value); } finally { _readWriteLock.ExitReadLock(); } } public void CopyTo(KeyValuePair[] array, int index) { _readWriteLock.EnterReadLock(); try { _dict.CopyTo(array, index); } finally { _readWriteLock.ExitReadLock(); } } public override bool Equals(Object obj) { _readWriteLock.EnterReadLock(); try { return _dict.Equals(obj); } finally { _readWriteLock.ExitReadLock(); } } public IEnumerator> GetEnumerator() { return new SafeEnumerator>(_dict.GetEnumerator(), _readWriteLock); } IEnumerator IEnumerable.GetEnumerator() { return new SafeEnumerator>(_dict.GetEnumerator(), _readWriteLock); } public override int GetHashCode() { _readWriteLock.EnterReadLock(); try { return _dict.GetHashCode(); } finally { _readWriteLock.ExitReadLock(); } } public bool Remove(TKey key) { _readWriteLock.EnterWriteLock(); try { return _dict.Remove(key); } finally { _readWriteLock.ExitWriteLock(); } } public override string ToString() { _readWriteLock.EnterReadLock(); try { return _dict.ToString(); } finally { _readWriteLock.ExitReadLock(); } } public bool TryGetValue(TKey key, out TValue value) { _readWriteLock.EnterReadLock(); try { return _dict.TryGetValue(key, out value); } finally { _readWriteLock.ExitReadLock(); } } #endregion }