Can a collection be modified by another thread during ToList()

class Sample
{
    private List<int> _list;
    public List<int> List
    {
        get 
        { 
            return _list.Select(p => p + p).Where(q => q % 2 == 0).ToList(); 
        }
    }

    public void Add(int n)
    {
        _list.Add(n);
    }

    public void Remove(int n)
    {
        _list.Remove(n);
    }
}

I have a situation similar to above in a multithreaded environment where Add, Remove and List are accessed by multiple threads simultaneously.

In some cases Collection was modified; enumeration operation may not execute is thrown in the List getter, which makes sense as threads can Add/Remove while the Select/Where operations are executing.

Can the list be modified by another thread during a call to ToList()? Meaning, would changing the getter to

return _list.ToList().Select(p => p + p).Where(q => q % 2 == 0);

be enough, or do I need to resort to locks around access to _list

Jon Skeet
people
quotationmark

There's no multi-threading protection in List<T>, so yes, another thread could modify the list during a ToList call. The results could be:

  • Everything's fine, and the resulting list has the new value
  • Everything's fine, and the resulting list doesn't have the new value
  • It sets your hard disk on fire (or other undefined behaviour)

Basically, it is not safe to use a List<T> from multiple threads without external synchronization, unless all the threads are just reading from it. You either need synchronization (e.g. using SynchronizedCollection<T> instead of List<T>, or handling the synchronization yourself), or a concurrent collection such as ConcurrentBag<T>.

people

See more on this question at Stackoverflow