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
  • 4,103
  • 5
  • 27
  • 37

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
  • 180,369
  • 20
  • 160
  • 215