首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >线程安全SortedDictionary

线程安全SortedDictionary
EN

Stack Overflow用户
提问于 2014-03-10 18:14:28
回答 2查看 4.5K关注 0票数 7

我创建了一个使用SortedDictionary存储和操作数据的类。除了在多线程环境中实现之外,该类非常有用。现在,我希望通过为内部SortedDictionary类编写一个包装类来确保类线程的安全。我想使用Reader-Writer Locks来实现这一点,但就目前而言,我只编写包装类本身就有问题。具体来说,我不知道如何为字典实现Enumerator。这是我现在的全班代码。

代码语言:javascript
复制
    public class ConcurrentSortedDictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
{
    #region Variables
    SortedDictionary<TKey, TValue> _dict;
    #endregion
    #region Constructors
    public ConcurrentSortedDictionary()
    {
        _dict = new SortedDictionary<TKey, TValue>();
    }

    public ConcurrentSortedDictionary(IComparer<TKey> comparer)
    {
        _dict = new SortedDictionary<TKey, TValue>(comparer);
    }

    public ConcurrentSortedDictionary(IDictionary<TKey, TValue> dictionary)
    {
        _dict = new SortedDictionary<TKey, TValue>(dictionary);
    }

    public ConcurrentSortedDictionary(IDictionary<TKey, TValue> dictionary, IComparer<TKey> comparer)
    {
        _dict = new SortedDictionary<TKey, TValue>(dictionary, comparer);
    }
    #endregion
    #region Properties
    public IComparer<TKey> 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<TKey, TValue>.KeyCollection Keys
    {
        get
        {
            return new SortedDictionary<TKey,TValue>.KeyCollection(_dict);
        }
    }

    public SortedDictionary<TKey, TValue>.ValueCollection Values
    {
        get
        {
            return new SortedDictionary<TKey, TValue>.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<TKey, TValue>[] array, int index)
    {
        _dict.CopyTo(array, index);
    }

    public override bool Equals(Object obj)
    {
        return _dict.Equals(obj);
    }

    IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
    {
        return GetEnumerator();
    }

    public IEnumerator<KeyValuePair<TKey, TValue>> 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‘不实现接口成员ConcurrentSortedDictionary'ConcurrentSortedDictionary.GetEnumerator()‘不能实现ConcurrentSortedDictionary.GetEnumerator,因为它没有匹配的返回类型’System.Collections.IEnDigator‘。

我在这里看了几篇与此有关的帖子,作为参考:

实现线程安全字典的最佳方法是什么?

但我没看到我做错了什么。任何援助都非常感谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-03-11 14:27:10

在落实了dvnrrs的建议后,我现在的班级工作得很好。我甚至为IEnumerable接口添加了一个包装类,以保护SortedDictionary的枚举(从本例中修改的代码:http://www.codeproject.com/Articles/56575/Thread-safe-enumeration-in-C)。以下是已更新的代码,其中包含了Reader-Writer Locks:

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Threading;

public class SafeEnumerator<T> : IEnumerator<T>
{
    #region Variables

    // this is the (thread-unsafe)
    // enumerator of the underlying collection
    private readonly IEnumerator<T> _enumerator;

    // this is the object we shall lock on. 
    private ReaderWriterLockSlim _lock;

    #endregion 

    #region Constructor

    public SafeEnumerator(IEnumerator<T> 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<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
{
    #region Variables

    private ReaderWriterLockSlim _readWriteLock = new ReaderWriterLockSlim();
    SortedDictionary<TKey, TValue> _dict;

    #endregion

    #region Constructors

    public ConcurrentSortedDictionary()
    {
        _dict = new SortedDictionary<TKey, TValue>();
    }

    public ConcurrentSortedDictionary(IComparer<TKey> comparer)
    {
        _dict = new SortedDictionary<TKey, TValue>(comparer);
    }

    public ConcurrentSortedDictionary(IDictionary<TKey, TValue> dictionary)
    {
        _dict = new SortedDictionary<TKey, TValue>(dictionary);
    }

    public ConcurrentSortedDictionary(IDictionary<TKey, TValue> dictionary, IComparer<TKey> comparer)
    {
        _dict = new SortedDictionary<TKey, TValue>(dictionary, comparer);
    }

    #endregion

    #region Properties

    public IComparer<TKey> 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<TKey, TValue>.KeyCollection Keys
    {
        get
        {
            _readWriteLock.EnterReadLock();
            try
            {
                return new SortedDictionary<TKey, TValue>.KeyCollection(_dict);
            }
            finally
            {
                _readWriteLock.ExitReadLock();
            }
        }
    }

    public SortedDictionary<TKey, TValue>.ValueCollection Values
    {
        get
        {
            _readWriteLock.EnterReadLock();
            try
            {
                return new SortedDictionary<TKey, TValue>.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<TKey, TValue>[] 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<KeyValuePair<TKey, TValue>> GetEnumerator()
    {
        return new SafeEnumerator<KeyValuePair<TKey, TValue>>(_dict.GetEnumerator(), _readWriteLock);
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return new SafeEnumerator<KeyValuePair<TKey, TValue>>(_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
}
票数 1
EN

Stack Overflow用户

发布于 2014-03-10 18:18:43

问题在于:

代码语言:javascript
复制
IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
{
    return GetEnumerator();
}

public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
    return _dict.GetEnumerator();
}

你需要:

代码语言:javascript
复制
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
    return _dict.GetEnumerator();
}

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

第二个非泛型GetEnumerator()是一个显式接口实现,需要它作为一个不幸的回滚回到C#中存在泛型和泛型集合之前的日子。

另请参阅:提供两个GetEnumerator方法-它们之间有什么区别? (特别是迈克尔·B的回答)。

然而如果您希望枚举与类的其他部分一样是线程安全的,您可能还需要编写您自己的线程安全IEnumerator类型,它与类中的读取器/写入器锁协作!

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22308067

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档