Is it safe to use List with Parallel.ForEach?

4

I'm doing a doing a crawler style method that takes a string list, makes a call to a website, inserts the return into another list, and returns.

My method is working, but it is very slow so I want to parallelize the calls. I searched for Parallel.ForEach easily solve this problem, but is it safe to use it with List ?

My current code:

private List<Veiculo> ObtemTodosVeiculos(List<string> modelos)
{
    List<Veiculo> veiculos = new List<Veiculo>();
    foreach (var modelo in modelos)
    {
        string retorno = GET(string.Format("https://192.168.0.1/modelo/{0}", modelo));
        var veiculo = Deserializa<Veiculo>(retorno);
        if (veiculo != null)
            veiculos.Add(veiculo);
    }
    return veiculos;
}
    
asked by anonymous 18.05.2016 / 23:40

2 answers

5
  

My method is working, but it is very slow so I want to parallelize the calls. I searched for Parallel.ForEach easily solve this problem, but is it safe to use it with List ?

No

List and any classes outside System.Collections.Concurrent are not thread-safe . Prefer one of the collections listed here .

Another way is protecting the list in a critical region , but this will bring other performance penalties , because List is not optimized for competition.

private Object obj = new Object();
...

var veiculo = Deserializa<Veiculo>(retorno);
lock (obj) 
{
    if (veiculo != null)
        veiculos.Add(veiculo);
}
    
18.05.2016 / 23:45
3

It depends. If you can ensure that the list will not be modified while Parallel.ForEach is running, then you will have no problem. If not, follow the suggestion of @CiganoMorrisonMendez.

From List<T> documentation on MSDN , section thread safe access: "It is safe to perform multiple read operations on a List, but problems can occur if the collection is modified while it is being read."

As Bruno Costa mentioned in the comment - in the above case there is no problem in using the modelos list in parallel. However, the veiculos list is being modified in multiple threads, so the type of this variable must be changed to some of the collections that are thread safe.

    
18.05.2016 / 23:48