-1

I am trying to understand when to use Dictionary vs ConcurrentDictionary because of an issue I had with one of the changes I made to a Dictionary.

I had this Dictionary

private static Dictionary<string, Side> _strategySides = null;

In the constructor, I am adding some keys and values to the Dictionary I created like this

_strategySides.Add("Combination", Side.Combo);
_strategySides.Add("Collar", Side.Collar);

This code was fine and had been running in all environments for a while now. When I added

_strategySides.Add("Diagonal", Side.Diagonal);

This code starts to break with exceptions “Index was outside the bounds of the array.” On the dictionary. Then I got into the concept of ConcurrentDictionary and its uses and that I needed to choose ConcurrentDictionary over Dictionary in my case since its a multi threaded application.

So my question to all you gurus is that why didn't it throw an exception all these days and it started when I added something to a dictionary. Any knowledge on this will be appreciated.

Camilo Terevinto
  • 31,141
  • 6
  • 88
  • 120
challengeAccepted
  • 7,106
  • 20
  • 74
  • 105

3 Answers3

2

As you mentioned, you have multi threaded application. Dictionary is not thread-safe and somewhere in your code you are reading dictionary simultaneously when adding item to it -> IndexOutOfboundsException.

This is mentioned in documentation:

A Dictionary can support multiple readers concurrently, as long as the collection is not modified. Even so, enumerating through a collection is intrinsically not a thread-safe procedure. In the rare case where an enumeration contends with write accesses, the collection must be locked during the entire enumeration. To allow the collection to be accessed by multiple threads for reading and writing, you must implement your own synchronization. For a thread-safe alternative, see ConcurrentDictionary.

Risto M
  • 2,919
  • 1
  • 14
  • 27
1

Check out the answer to this question: c# Dictionary lookup throws "Index was outside the bounds of the array"

It seems as though receiving this error on a dictionary is specific to a thread safety violation. The linked answer provides 2 ways to deal with the issue, one is concurrentdictionary.

If I had to guess why it didn't happen before: you are adding the entries in your constructor for a static object, which means only 1 writer, and no readers yet.

Your new entry is probably being added outside the constructor? Another thread could be reading while this write is being attempted, and is not allowed.

user7396598
  • 1,269
  • 9
  • 6
  • I am adding the new entry in the constructor where others are being added, thats what makes me so interested to know "why now"? – challengeAccepted Feb 08 '18 at 18:56
  • @Ram If your only writes are done in the constructor of a static object you do not need to rewrite everything to concurrentdictionary. the nature of static is there is only one. Check your initial definition "private static Dictionary _strategySides = null;" You may want to just new up the dictionary right there, so it does not "exist" between this definition and the constructor filling it out. An object = null is still an accessible object. – user7396598 Feb 08 '18 at 19:06
1

Dictionary is not thread-safe, and if you modify it while being accessed from multiple threads, all kinds of weird stuff can happen, including appearing to "work"... until it doesn't. Either protect it with a lock, or use the data structure that was specifically designed for multi-threaded use (i.e. ConcurrentDictionary).

So why did it "work" - that's very difficult to know definitively, but my bet would be on either simply not seeing the problem (i.e. the internal dictionary state was corrupted but you didn't notice it due to your usage patterns), or simply being "lucky" on execution timings (e.g. you could have inadvertently "synchronized" the threads through the debugger).

The point is: whatever it was, you cannot rely on it! You have to do the "right thing" even if the "wrong thing" appears to "work". That is the nature of multi-threaded programming.

Branko Dimitrijevic
  • 50,809
  • 10
  • 93
  • 167