11
votes

I'm consistenlty getting this error on a multithreading .net 3.5 application

ERROR 26 Exception thrown. Details: 'System.IndexOutOfRangeException: Index was outside the bounds of the array.

at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)

at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)

I think I know how to fix it (adding locks where appropiate) but I'd like to be able to recreate this problem on my local environment so I'll be sure that I fixed it and also I be able to add a unit test for it.

Do you know any consistent way to recreate this?

4
Is there a particular reason you're not using ConcurrentDictionary?Sconibulus
@Sconibulus: this app is 3.5, can't use ConcurrentDictionary :(StackOverflower

4 Answers

9
votes
Dictionary<string, string> dict = new Dictionary<string, string>();

Task.Factory.StartNew(() => { while (true) dict["a"] = "a"; });
Task.Factory.StartNew(() => { while (true) dict.Remove("a"); });
4
votes

Unfortunately, being consistent in a multithreaded application where race conditions occur is simply not achievable.

The hardware differences alone between your machine and the production one will ensure that when a problem does occur, it may not be in the same location. Even if the hardware is the same, software differences (especially those background services) can lead to timing differences and therefore a situation where it's just not repeatable.

Heck, if those threads have dependencies on external resources (like DB calls) the network latency differences between production and your test box might ensure that you can never duplicate it.

Shy of having a debugger on the server (bad bad idea), the best thing you can do is a visual analysis of the code, fix the parts you think need to be fixed, test it (as well as you can) then release and watch it in production.

1
votes

This won't help you to recreate the error locally, but to remove the error completely, the msdn docs for the generic Dictionary<TKey, TValue> say:

For a thread-safe alternative, see ConcurrentDictionary<TKey, TValue>.

The docs for ConcurrentDictionary<TKey, TValue> say:

Represents a thread-safe collection of key-value pairs that can be accessed by multiple threads concurrently.

Note however, that ConcurrentDictionary<TKey, TValue> is only available in .Net 4 and up.

0
votes

Why don't you create a wrapper for the Dictionary with a ReaderWriterLockSlim in it. That way you have all locking done in one class.