Dani
Dani

Reputation: 2036

Parallel.ForEach add and read ConcurrentBag, is safe?

¿It's safe and correct, inside parallel.foreach, add and read to/from a concurrent bag?

Example (in VB.net):

Dim myConcurrentBag As New ConcurrentBag(Of myClass)

Parallel.ForEach(elementList, Sub(element)
   Try
        Dim newObject as New myClass
       
        newObject.Property1 = element.PropertyX
        
        ' Check if item is inserted inside myConcurrentBag
        ' ¿IS THIS LINE CORRECT?
       If (myConcurrentBag.Select(Function(x) x.Property1).Contains(newObject.Property1)) Then
           Return
       End If
       myConcurrentBag.Add(newObject)

   Catch ex As Exception
       ' Log exception
   End Try
End Sub)

And finally, this is the best way to do it, right?:

Dim myConcurrentDictionary As New ConcurrentDictionary(Of String, myClass)

Parallel.ForEach(elementList, Sub(element)
   Try
        Dim newObject as New myClass
       
        newObject.Property1 = element.PropertyX
        
        ' Check if item is inserted inside myConcurrentDictionary 
        ' ¿IS THIS LINE CORRECT?
       If (myConcurrentDictionary.ContainsKey(newObject.Property1)) Then
           Return
       End If
       
       myConcurrentDictionary.TryAdd(newObject.Property1, newObject)

   Catch ex As Exception
       ' Log exception
   End Try
End Sub)

Upvotes: 0

Views: 256

Answers (1)

Alexey Adadurov
Alexey Adadurov

Reputation: 184

I understand your intention is to have unique items in terms of PropertyX after the execution of Parallel.ForEach is completed.

As enumeration of ConcurrentBag runs over a point in time snapshot of the content, another task may insert an object with the same value of the property without Select() seeing this new object, and thus the uniqueness requirement will not be met.

Please check this question as well -- Adding and removing elements of a ConcurrentBag during enumeration

Upvotes: 1

Related Questions