0

I have a ConcurrentDictionary that I am adding elements to.

The key is not unique, and may reflect multiple values.

  1. I iterate through the keys to get the unique names of them
  2. I iterate through the values by key to get a list of the values
  3. The compiler crashes on the "Next" statement with the following error:

Additional information: Conversion from string "LOS ANGELES" to type 'Integer' is not valid.

So, if I have a key(of String), how can I get the values associated with that key?

    Dim dict As New ConcurrentDictionary(Of String, String)
    dict.TryAdd("LOS ANGELES", "black")

    dict.TryAdd("LOS ANGELES", "yellow")
    dict.TryAdd("LOS ANGELES", "blue")
    dict.TryAdd("LOS ANGELES", "orange")
    dict.TryAdd("LOS ANGELES", "yellow")
    dict.TryAdd("LOS ANGELES", "yellow")
    dict.TryAdd("LOS ANGELES", "yellow")
    dict.TryAdd("LOS ANGELES", "yellow")
    dict.TryAdd("LOS ANGELES", "orange")


    For Each stKeys As String In dict.Keys
        If stKeys <> Nothing Then
            For Each values In dict.Values(stKeys)
                If values <> Nothing Then
                       Debug.Print(values.ToString)
                End If
            Next
        End If
    Next

UPDATE: How I solved the problem:

I used a list, passing a structure to it, with locking instead of a ConcurrentDictionary, and at the end of that, I sorted those items into a NameValueCollection, like so:

Structure structCities
          CityName as String
          vColor as string
End Structure

DIM dataList as new List(of structCities)
DIM vData as new structCities

with vData
     .CityName = "LOS ANGELES"
     .vColor = "black"
end with: dataList.add(vData)

with vData
     .CityName = "LOS ANGELES"
     .vColor = "black"
end with: dataList.add(vData)

with vData
     .CityName = "LOS ANGELES"
     .vColor = "black"
end with: dataList.add(vData)

with vData
     .CityName = "LOS ANGELES"
     .vColor = "black"
end with: dataList.add(vData)

with vData
     .CityName = "LOS ANGELES"
     .vColor = "yellow"
end with: dataList.add(vData)

Dim dict As New NameValueCollection
For Each c In dataList 
       dict.Add(c.CityName, c.vColor)
Next
  • 1
    your code will store only the first item in the dictionary (LOS ANGELES, "black"). All other calls to `TryAdd` will return `false` cause the key LOS ANGELES does already exist. – Jehof Jul 28 '16 at 09:56
  • The thing is, it doesn't just store the first value. When you put your mouse over dict.values(), it returns every value without a problem, but you are correct in saying keys must be unique. –  Jul 28 '16 at 17:46
  • So you went from ConcurrentDictionary (with non-unique keys) to a List? – paparazzo Jul 28 '16 at 18:11
  • A structured list using SyncLock to add elements from within around 100 parallel iterations, each with simple for...next... scanning iterations inside of them, finally taking the output and dumping it into a NameValueCollection. Yes. Because if you use a dictionary of any kind, while in parallel, the performance loss is obvious, since the overhead required to keep track of the dictionary entries is much higher than a "dumb list" which has no indexes/keys to track. –  Jul 28 '16 at 22:25
  • In my actual code, (which in every thread cycle handles more than 5,000,000 data processing points through parallel iterations), the time it took to add to a Dictionary while iterating (or even ConcurrentDictionary, or ConcurrentBag) slowed the process down to around 5 seconds, even locking while using the List and passing it off to a NameValue collection afterwards, the time was dropped down to roughly 700ms on an i7 octo-core. –  Jul 28 '16 at 22:27
  • It works flawlessly, but I need to work my way down to around 30ms latency, I may have to write my own concurrent thread-safe collection object in C if I don't find what I need. –  Jul 28 '16 at 22:30

1 Answers1

0

The Parameter that is passed to the dict.Values(int) method is the index of the element, not the key. If you want to adress the value by ist key, use

For Each values In dict(stKeys)

However, as Jehof already mentioned in his comment, you can't have a ConcurrentDictionary wit ha non-unique key. It will only add the first element, the other calls will fail.

TheCodingDamian
  • 443
  • 2
  • 12
  • That's unfortunate. I had to sacrifice performance I really can't afford to lose and convert the ConcurrentDictionary to a NameValueCollection when it's time to handle the sorting after the fact, which allowed me the functionality I was looking for, but at a very high cost. –  Jul 28 '16 at 17:44
  • I amended my answer to show my "solution", is there any other high volume, concurrent way to do what I am trying to do? –  Jul 28 '16 at 17:53
  • To be honest, I'm not really an expert when it Comes to collections. This guide on MSDN Looks helpful: [link](https://msdn.microsoft.com/en-us/library/6tc79sx1(v=vs.110).aspx) The thing it recommends for you is a NameValueCollection though, seems like there is no faster way. Maybe there are some external libraries that provide the collection you need. If not you will have to either stick with the NameValueCollection or, as you already said, write your own one... – TheCodingDamian Jul 29 '16 at 06:28
  • Yeah I'm using that now but it isn't thread safe. Nothing exists. I'll have to build my own and put it up on codeproject after. Thanks for the input. –  Jul 30 '16 at 08:00