c# - Task Parallel.ForEach loop Error when removing items "Index was outside the bounds of the array. " -
i trying remove items generic list of objects in foreach loop. when doing same thing task parallel library loop getting error. index outside bounds of array.
following code
list<string> lstsubscriberdidtransaction = ...; // initialization var lstsubscriber = jsonconvert.deserializeobject<list<subscriberinfoshortenobject>>(somestring); foreach (string strid in lstsubscriberdidtransaction) { lstsubscriber.removeall(h => h != null && h.msisdn == strid); } //parallel.foreach(lstsubscriberdidtransaction, msisdn => lstsubscriber.removeall(h => h != null && h.msisdn == msisdn));
can me in using .net 3.5. task parallel library http://nuget.org/packages/taskparallellibrary
the list
class not designed concurrent write (/remove) operations, stated in msdn:
it safe perform multiple read operations on list, issues can occur if collection modified while it’s being read. ensure thread safety, lock collection during read or write operation. enable collection accessed multiple threads reading , writing, must implement own synchronization. collections built-in synchronization, see classes in system.collections.concurrent namespace. inherently thread–safe alternative, see immutablelist class.
for data structures supporting concurrent access, see this linked article.
to clarify why problem arises list
class: removeall
operation iterate on list instance , match predicate against every contained instance. if predicate evaluates true, index of matched instance used remove entry. if operation performed in concurrent matter, thread may have removed entry, index no longer valid or point instance not matching predicate. operation therefore not threadsafe , not give results expecting. viewing pleasure, given code decompiled method list
class:
public int removeall(predicate<t> match) { if (match == null) throwhelper.throwargumentnullexception(exceptionargument.match); int index1 = 0; while (index1 < this._size && !match(this._items[index1])) ++index1; if (index1 >= this._size) return 0; int index2 = index1 + 1; while (index2 < this._size) { while (index2 < this._size && match(this._items[index2])) ++index2; if (index2 < this._size) this._items[index1++] = this._items[index2++]; } array.clear((array) this._items, index1, this._size - index1); int num = this._size - index1; this._size = index1; ++this._version; return num; }
to give more hints: not use parallel code, not without big changes. optimize data structure , simplify statement.
hashset<string> lstsubscriberdidtransaction = ... ... lstsubscriber.removeall(h => h != null && lstsubscriberdidtransaction.contains(h.msisdn))
this should improve performance, more need more insight code.
Comments
Post a Comment