vb.net - Parallel.ForEach gives different results each time -
please me convert following loop parallel loop. tried using parallel.foreach , concurrentbag instead of hashset, wied thing "matched" returns every time different results.
i can't figure out... because of thread safety issues?
keywords list contains 500 unique strings, each 1-3 words in lenght.
items contains 10000 items.
original code:
dim items ienumerable(of item) = db.items.getall dim keywords hashset(of string) dim matched hashset(of item) each item in items each keyword in keywords if regex.ismatch(headline, string.format("\b{0}\b", keyword), regexoptions.ignorecase or regexoptions.cultureinvariant) if not matched.contains(item) matched.add(item) end if end if next next
attempt convert
dim items ienumerable(of item) = db.items.getall dim keywords hashset(of string) dim matched concurrent.concurrentbag(of item) threading.tasks.parallel.foreach(of item)(items, sub(item) each keyword in keywords if regex.ismatch(item.title, string.format("\b{0}\b", keyword), regexoptions.ignorecase or regexoptions.cultureinvariant) if not matched.contains(item) matched.add(item) end if continue end if next end if
yes, code isn't thread-safe. using thread-safe collections won't make code automatically thread-safe, still need use them correctly.
your problem after contains()
finishes before add()
called on 1 thread, add()
can called on thread (and same can possibly happen while contains()
executes).
what need to:
- use locking (this means won't need use thread safe collection anymore); or
- use
concurrenthashset
. there no such class in .net, can useconcurrentdictionary
instead (even if doesn't fit needs exactly). instead of callcontains()
,add()
,matched.tryadd(item, true)
,true
there becauseconcurrentdictionary
needs value.
Comments
Post a Comment