0

How can I convert this code to a Parallel.ForEach (WorkingDict is a HybridDictionary)?

I've included my code below (Please don't judge my methods. This tool is my first attempt at classes, and I'm starting to believe I've made it fairly complex and laborious to work with).

Dim Cntr As Integer = 0, Bool1 As Boolean = False
For Each Obj As Object In BusLoadDict.Keys
    Cntr = 0
    Bool = False
    bool1 = False
    For Each Obj2 As Object In PNodesDict.Keys
        For Each Obj1 As Object In DirectCast(PNodesDict.Item(Obj2.ToString), PNodeClass) _
            .PNodeDescriptionDictOfDicts.Keys
            If Obj1.ToString.Contains("forecast zone") Then
                If DirectCast(DirectCast(DirectCast(PNodesDict.Item(Obj2.ToString),  _
                            PNodeClass).PNodeDescriptionDictOfDicts, HybridDictionary).Item("forecast zone"),  _
                    HybridDictionary).Contains(BusLoadDict.Item(Obj.ToString)) Then
                    Bool = True
                    Cntr += 1
                    If Cntr = 2 Then GoTo 1
                End If
            End If
            If Obj1.ToString.Contains("aggregate") Then
                Bool1 = True
                If DirectCast(DirectCast(DirectCast(PNodesDict.Item(Obj2.ToString),  _
                            PNodeClass).PNodeDescriptionDictOfDicts, HybridDictionary).Item("aggregate"),  _
                    HybridDictionary).Contains(BusLoadDict.Item(Obj.ToString)) Then
                    Bool = True
                    Cntr += 1
                    If Cntr = 2 Then GoTo 1
                End If
            End If
        Next
    Next
1:          If Bool = False Then
    SBuilder.AppendLine("Bus PNode " & Obj.ToString & " was not mapped to the forecast zone pnodes.")
    End If
    If bool1 = False Then
        SBuilder.AppendLine("Bus PNode " & Obj.ToString & " was not mapped to the aggregate pnodes.")
    End If
Next

Here is the error code.

Error   1   Overload resolution failed because no accessible 'ForEach' can be called with these arguments:
    'Public Shared Function ForEach(Of TSource)(source As System.Collections.Concurrent.OrderablePartitioner(Of TSource), body As System.Action(Of TSource, System.Threading.Tasks.ParallelLoopState, Long)) As System.Threading.Tasks.ParallelLoopResult': Data type(s) of the type parameter(s) cannot be inferred from these arguments. Specifying the data type(s) explicitly might correct this error.
    'Public Shared Function ForEach(Of TSource)(source As System.Collections.Concurrent.Partitioner(Of TSource), body As System.Action(Of TSource, System.Threading.Tasks.ParallelLoopState)) As System.Threading.Tasks.ParallelLoopResult': Data type(s) of the type parameter(s) cannot be inferred from these arguments. Specifying the data type(s) explicitly might correct this error.
    'Public Shared Function ForEach(Of TSource)(source As System.Collections.Concurrent.Partitioner(Of TSource), body As System.Action(Of TSource)) As System.Threading.Tasks.ParallelLoopResult': Data type(s) of the type parameter(s) cannot be inferred from these arguments. Specifying the data type(s) explicitly might correct this error.
    'Public Shared Function ForEach(Of TSource)(source As System.Collections.Generic.IEnumerable(Of TSource), body As System.Action(Of TSource, System.Threading.Tasks.ParallelLoopState, Long)) As System.Threading.Tasks.ParallelLoopResult': Data type(s) of the type parameter(s) cannot be inferred from these arguments. Specifying the data type(s) explicitly might correct this error.
    'Public Shared Function ForEach(Of TSource)(source As System.Collections.Generic.IEnumerable(Of TSource), body As System.Action(Of TSource, System.Threading.Tasks.ParallelLoopState)) As System.Threading.Tasks.ParallelLoopResult': Data type(s) of the type parameter(s) cannot be inferred from these arguments. Specifying the data type(s) explicitly might correct this error.
    'Public Shared Function ForEach(Of TSource)(source As System.Collections.Generic.IEnumerable(Of TSource), body As System.Action(Of TSource)) As System.Threading.Tasks.ParallelLoopResult': Data type(s) of the type parameter(s) cannot be inferred from these arguments. Specifying the data type(s) explicitly might correct this error. C:\My Folder\Market Operations\VB.net\Market Validations Tool\Market Validations Tool\Market Operations Tool.vb 6361    9   Market Validations Tool
Ryan Gates
  • 4,501
  • 6
  • 50
  • 90
JoeB
  • 297
  • 4
  • 20
  • I have edited your title. Please see, "[Should questions include “tags” in their titles?](http://meta.stackexchange.com/questions/19190/)", where the consensus is "no, they should not". – John Saunders Mar 06 '13 at 03:38
  • Yes, your code is rather complex to start with, I would looking into refactoring it first. – Victor Zakharov Mar 06 '13 at 16:02

1 Answers1

2

Yes You can do it like this.

Dim WorkingDict As New HybridDictionary
WorkingDict.Add("k1", "v1")
WorkingDict.Add("k2", "v2")
Parallel.ForEach(WorkingDict.Cast(Of Object),
                 Sub(DictObject As KeyValuePair(Of String, String))
                     ' do something
                 End Sub)

You need to use the IEnumerable.Cast operator because Parallel.Foreach only works with generic collections. HybridDictionary is a non-generic collection.

But keep in mind that this is a very simple [empty] example and more complex parallel operations require many considerations such as locking shared resources etc. You could always consider using a System.Collections.ConcurrentDictionary, which handles locking shared resources if needed. A SO post on this. Example:

Dim WorkingDict As New ConcurrentDictionary(Of String, String)
' ConcurrentDictionary has no Add operator, so to replicate it, use AddOrUpdate
' and just pass the same value whether it is being added or updating
WorkingDict.AddOrUpdate("key1", "value1", Function(key, oldvalue) "value1")
WorkingDict.AddOrUpdate("key2", "value2", Function(key, oldvalue) "value2")
Parallel.ForEach(WorkingDict,
                 Sub(DictObject as DictionaryEntry)
                     ' do something
                 End Sub)
Community
  • 1
  • 1
djv
  • 15,168
  • 7
  • 48
  • 72
  • I'm getting a "Option Strict On requires each lambda expression to be declared with an 'As' clause if it's type cannot be inferred." error with the (DictObject). – JoeB Mar 06 '13 at 03:04
  • Edited to satisfy your Option Strict On (I don't have the IDE in front of me, forgive me) – djv Mar 06 '13 at 03:06
  • Edited again. This time arguments are explicitly typed by casting. Also, iterating over each `KeyValuePair` of the Dictionary, instead of Keys. Your `DictObject` will be a `KeyValuePair` instead of a key, so to get the key just do `DictObject.Key`. – djv Mar 06 '13 at 03:48
  • Edited once more, this should do it – djv Mar 06 '13 at 15:47
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/25709/discussion-between-dan-verdolino-and-joeb) – djv Mar 06 '13 at 16:47