If you're more interested in reading, you should use a ReaderWriterLockSlim
.
This is a locking primitive that allows multiple readers or one writer to enter the critical region at any given time. This will incur virtually no performance hit while the dictionary is being read by multiple threads, and apply mutual exclusion only when a thread tries to write.
You would implement it as so (I omitted most methods for brevity - I left Add
as a writer example, and Contains
as a reader example):
public class CustomDictionary<TKey, TValue> : IDictionary<TKey, TValue>
{
private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
private readonly IDictionary<TKey, TValue> _dictionary = new Dictionary<TKey, TValue>();
public bool Contains(KeyValuePair<TKey, TValue> item)
{
_lock.EnterReadLock();
try
{
return _dictionary.Contains(item);
}
finally
{
_lock.EnterReadLock();
}
}
public void Add(KeyValuePair<TKey, TValue> item)
{
_lock.EnterWriteLock();
try
{
_dictionary.Add(item);
}
finally
{
_lock.ExitWriteLock();
}
}
}
Now, the GetEnumerator
is a little trickier to lock, because the dictionary will actually be read after calling GetEnumerator, not while it's being called.
So you should implement the enumerator yourself and apply a read-lock like this, so that the lock will be held while the collection is being enumerated:
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
_lock.EnterReadLock();
try
{
foreach (var entry in _dictionary)
yield return entry;
}
finally
{
_lock.ExitReadLock();
}
}