Fragensteller
NullReferenceException in Parallel.ForEach

Frage
-
Hallo,
folgender Code bringt in der Parallel.ForEach einen NullReferenceException,
mit normaler foreach kommt kein Fehler:
public Boolean insertListOfPoints(IList<BeanPunkte> listOfPunkte) { if (listOfPunkte == null) return true; if (listOfPunkte.Count == 0) return true; Parallel.ForEach<BeanPunkte>(listOfPunkte, item => { item.matriksinsert = true; // bei der Exception ist item == null !? item.eingelesenam = DateTime.Now; }); return insertAndCommitListOfBean(listOfPunkte.ToList<Object>()); // fügt die Liste von Punkten in die DB ein (Update) }
...mmm... Wie kann das bei einer ForEach sein?
Alle Antworten
-
... Au backe, in der listOfPunkte sind tatsächlich "null-Objekte" drinn, dürften aber nicht,
da ich vor dem Einfügen in der Liste die BeanPunkte auf null prüfe:
Parallel.ForEach<CADdyPunkt>(quelle.DBKPointList.Values, cADdyPunkt => { if (!allPunkteFromDB.ContainsKey(cADdyPunkt.Punktnummer)) { newPunkt = ToolsPunkte.getBeanPunktFromCADdyPunkt(cADdyPunkt, idProject); if (newPunkt != null) newPoints.Add(newPunkt); else newPunkt = null; // Test für den Lauf, wird nie angesprungen } });
Das eigenartige ist, dass immer die Einträge mit folgendem Indexen null sind: 32, 128, 1024, 2048 !
Kann das an der Partitionierung in der Parallel.ForEach liegen?
-
... hab erst einmal ein QuickAndDirty dafür gefunden:
// nach der Parallel.ForEach
while (newPoints.Contains(null)) { newPoints.Remove(null); }
aber dir Frage bleibt trotzdem woher kommen die "blöden" null-Werte in der Liste
und wie verhindert man diese?
-
Hallo Mario,
Dein Problem dürfte daran liegen, dass Du keine threadsicherere Auflistung hast.
Und selbst mit der kannst Du so nicht auf darauf zugreifen.Selbst wenn ContainsKey noch false liefert, so könnte ein zweiter Thread eben
jenen newPunkt erzeugen und einfügen.
Und sind mehr als zwei aktiv, könnte das mehrfach passieren.Zu den 32, ... 2048:
Das wird sich in dem Moment manifestieren, wenn die Liste vergrößert werden muss,
da die internen Strukturen dabei üblicherweise verdoppelt werden.Du solltest erstmal auf Parallel verzichten und Dich in die Grundlagen einarbeiten:
Task Parallel LibraryIm allgemeinen gilt eh:
Für das Durchlaufen einer Auflistung mit minimaler Verarbeitung lohnt eine Parallelisierung nicht.Gruß Elmar
-
Hallo Mario,
für ein reines Kopieren / Übertragen wie Du es oben andeutest, lohnt es i. a. gar nicht,
denn das würde eine Synchronisierung benötigen, siehe dazu:
Potenzielle Fehler bei Daten- und AufgabenparallelitätErst wenn das Erzeugen (bzw. Übertragen) mit aufwändigeren Aktionen
verbunden ist kann sich das lohnen.
Aber dazu will dann das Verwenden von Sperren, Datenparallelität usw. verstanden sein.
Davon ist oben aber nichts zu sehen, deswegen der Ratschlag sich zunächst in die Grundlagen einzuarbeiten,
denn bei TPL / PLINQ ist nicht damit getan, ein Parallel. zu schreiben.Gruß Elmar