Concurrent collections provide thread-safe operations. ConcurrentDictionary<TKey, TValue>
implements the interface IEnumerable<T>
which does not require the interactions to be thread-safe, although most operations are thread-safe since they make use of GetEnumerator()
. However, methods such as ToList()
are not thread-safe, even when used on thread-safe collections due to an optimized copy mechanism for types implementing the interface ICollection<T>
, and introduce race conditions.
More critical is the fact that the concurrent collections often provide similarly called methods that are thread-safe. This constellation can lead to accidentally use LINQ method instead of the one of the collection.
Do not directly use LINQ's extension methods like ToList()
. Look for methods provided by the concurrent collection itself.
The other concurrent collection types, such as ConcurrentQueue<T>
, do not implement the interface ICollection<T>
and are therefore not subject to the optimized copy mechanism.
It is important to note that this behavior is undocumented and is subject to change. However, one may observe the race condition through experimenting as well as in the relevant implementations of Enumerable.ToList and List.