Is it safe to use List with Parallel.Foreach?

Asked

Viewed 1,328 times

4

I’m making one by making a style method Crawler which receives a string list, makes a call on a website, inserts the return into another list and returns.

My method is working, but it’s too slow, so I want to parallelize the calls.
So I researched the Parallel.ForEach easily solves this problem, but it is 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;
}
  • best solution to your problem is to make your method GET asynchronous. This way you would get a Task list and could use Task.WaitAll to wait for all "at the same time". But be careful with this. Your method GET have to use asymcnrone methods as well. It’s not just get there and write async that everything will work wonder... The best is to use a client who supports this

2 answers

5


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

Not

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

Another way is protect 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);
}

3

It depends. Whether you can ensure that the list will not be modified while the Parallel.ForEach is running so you will have no problem. Otherwise, follow @Ciganomorrisonmendez’s suggestion.

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

As Bruno Costa mentioned in the comment - in the above case there is no problem in using the list modelos in parallel. However, the list veiculos is being modified into multiple threads, so the type of this variable should be changed to one of the threadsafe collections.

  • His case involves a modification. It is very dangerous to parallel his example only with List.

  • 1

    By code snippet, the modification is done in the list veiculos, while the parallelization would be done on the list modelos. If this is only the case (i.e., there are no other modifications that are not shown), then there should be no problems.

  • @Yes, he’s going to have problems. It’s true that the Parallel.ForEach will go through all the elements of modelos, but this does not imply that the writings to veiculo have no problems.

  • My goal is to use only a list that will be instantiated outside the Parallel.ForEach, but I will use it only to add items, I will not use as reading, still have problem?

  • @Brunocosta, you’re right - the parallelization in the list modelos is safe, but the list veiculos should be defined as a thread-safe list (from System.Collections.Concurrent).

Browser other questions tagged

You are not signed in. Login or sign up in order to post.