0

I have a very strange problem with LINQ "order by" and Parallel.Foreach

Specifically, this code works:

IList<IEntitaAssociabile> result = new List<IEntitaAssociabile>();

foreach(PraticheAperteNonAssegnate pratica in praticheAperteNonAssegnate)
{
    result.Add(new EntitaAssociabile
    {
          Id = pratica.ID_Prat,
          TipologiaEntita = TipologiaEntita.Pratica,
          DataApertura = pratica.DataAper.Value,
          TipologiaPratica = pratica.Cod_TpPrat,
          NomeCliente = pratica.Nominativo,
          NumeroPraticheDaAssociare = null,
          TipologiaEntitaPadre = GetEntitaPadre(pratica, praticheLotti, praticheSottolotti),
          IdEntitaPadre = GetIdEntitaPadre(pratica, praticheLotti, praticheSottolotti)
    });
}

return result.OrderBy(x => x.Id).ToList();

If I simply change foreach statement with Parallel.Foreach:

 IList<IEntitaAssociabile> result = new List<IEntitaAssociabile>();

 Parallel.ForEach(praticheAperteNonAssegnate, (pratica) =>
 {
      result.Add(new EntitaAssociabile
      {
           Id = pratica.ID_Prat,
           TipologiaEntita = TipologiaEntita.Pratica,
           DataApertura = pratica.DataAper.Value,
           TipologiaPratica = pratica.Cod_TpPrat,
           NomeCliente = pratica.Nominativo,
           NumeroPraticheDaAssociare = null,
           TipologiaEntitaPadre = GetEntitaPadre(pratica, praticheLotti, praticheSottolotti),
           IdEntitaPadre = GetIdEntitaPadre(pratica, praticheLotti, praticheSottolotti)
      });
  });

  return result.OrderBy(x => x.Id).ToList();

On the "order by" I have a "Null object reference exception"

I can't understand why with foreach the code works but not with Parallel.Foreach.

Can you help me and explain what's the problem?

Eliahu Aaron
  • 1
  • 4
  • 26
  • 35

1 Answers1

7

Well, List<T> is not thread safe, that's why adding to result within Parallel.ForEach leads to problems. If you insist on parallel execution, try PLinq (Parallel Linq) instead:

IList<IEntitaAssociabile> result = praticheAperteNonAssegnate
  .AsParallel()
  .Select(pratica => new EntitaAssociabile() {
     Id = pratica.ID_Prat,
     ...
   })
  .OrderBy(item => item.Id)
  .ToList();

Comment out .AsParallel() if you want to switch to good old Linq.

Dmitry Bychenko
  • 165,109
  • 17
  • 150
  • 199