5

I have to remove items from ConcurrentDictionary by some keys. Like this:

ConcurrentDictionary<SomeClass, string> dict = new ConcurrentDictionary<SomeClass, string>();
//adding some values
var keys = dict.Keys.Where(k => k.Name == "Example");
foreach (var key in keys)
    dict.TryRemove(key, out _);

The question is: I am enumerating the keys collection when is start looping. What if somebody will change the dict at the same time? Does dict.Keys returns a snapshot?

2
  • 1
    It returns a copy. See here. Commented Dec 28, 2017 at 6:13
  • 1
    It returns a snapshot (so yes it will work fine). I would suggest using var keys = dict.Select(z => z.Key).Where(k => k.Name == "Example"); to reduce the need for snapshot (i.e. locking) - i.e. it will generally be faster. Or just foreach over the dictionary like in the duplicate. Commented Dec 28, 2017 at 7:17

2 Answers 2

5

Look at source code:

public ICollection<TKey> Keys
{
    get { return GetKeys(); }
}

private ReadOnlyCollection<TKey> GetKeys()
{
    int locksAcquired = 0;
    try
    {
        AcquireAllLocks(ref locksAcquired);

        int count = GetCountInternal();
        if (count < 0) throw new OutOfMemoryException();

        List<TKey> keys = new List<TKey>(count);
        for (int i = 0; i < _tables._buckets.Length; i++)
        {
            Node current = _tables._buckets[i];
            while (current != null)
            {
                keys.Add(current._key);
                current = current._next;
            }
        }

        return new ReadOnlyCollection<TKey>(keys);
    }
    finally
    {
        ReleaseLocks(0, locksAcquired);
    }
}

It locks collection and returns copy of keys

Sign up to request clarification or add additional context in comments.

Comments

4

All public and protected members of ConcurrentDictionary are thread-safe and may be used concurrently from multiple threads. However, members accessed through one of the interfaces the ConcurrentDictionary implements, including extension methods, are not guaranteed to be thread safe and may need to be synchronized by the caller.

from https://msdn.microsoft.com/en-us/library/dd287191(v=vs.110).aspx#Anchor_10

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.