Main Site Documentation

HashTable and an IndexOutOfRangeException


#1

Hello all

I have a bug in my code that throw an IndexOutRange exception while running:

string st = Playsets.Hashtableofvariables[1000].ToString();

As you can easily imagine Hashtableofvariables is an hashtable of variable ??? (sorry for my bad imagination :smiley: in naming convention)

The value stored at key 1000 is modified by a separate thread like the following one:

public void Thread_Rx()
        {
        while (true)
            {
            HtV[1000]=new_value;
            Thread.Sleep(10);
            }
        }

The exception occurs after 20 to 30 seconds. When VS stops, it always stops at the same line and when I list all the entry in the Hastable I see one with key 1000. So I do not know what is wrong and how to debug that. Any idea?


#2

Your array has 1000 element but Index 1000 is element #1001 :wink:

Element 1000 is index 999.

Edit: corrected “has” instead of “as”.


#3

Hard to say. show more code.

@ Bec He said it is a hashtable, so 1000 can be a valid key.


#4

Exactly architect the hashtable seems valid, and key 1000 is stored at index 570 in the current case (I don’t know how CLR compute the hash code but it seems to be always the same index for this <key,value> pair. Moreover it allocates an array of 1024 element even for this dummy case of two single pairs to store… anyway this does not seems to be the cause of the problem.

If I protect the hash table access with :

if (Playsets.Hashtableofvariables.Contains(1000))
{string st = Playsets.Hashtableofvariables[1000].ToString();
  byte[] bytes = System.Text.Encoding.UTF8.GetBytes(st);
                cdc.Write(bytes,0,bytes.Length);}

But I do not understand why I need such a precaution in this case. The playsets is declared as static… so GC should not delete it.

[EDIT]: I believed that the if would solve the issue but still have the exception while executing:

                if (Playsets.Hashtableofvariables.Contains(1000))

This is strange… any idea on how to solve or isolate this problem?


#5

Oops :-[


#6

You have two threads accessing an object without locking. Trying locking before accessing.


#7

@ Mike yes you may be true. I didn’t believe that locking was needed in this situation (a reading thread and a writing thread). I will try that. Do you know if there’s some high level mechanisms for such a lock? (mutex… or something else?)

Should I lock the opposite thread?

I think I need a deep dive in System.threading :wink:


#8

Hashtable has a SyncRoot property that you could lock on when writing or reading the hashtable.


#9

All threads that share an object need to use locking, regardless of whether they read or write.

This is typically the way I lock:


lock(theObject)
{
     ... access the theObject here

}

#10

This may help explain why your separate calls to Contains and the indexer could fail:


#11

Hi everyone and many thanks for your answers. It helps me a lot but I still have some doubts about locking mechanisms.

In fact I was locking like the following code:

T1:
lock(myHashTable.SyncRoot){
if(!myHashTable.Contains(a_key))
myHashTable.Add(a_key, its_value)}

T2:
lock(myHashTable.SyncRoot){
if(!myHashTable.Contains(a_key))
value=myHashTable[a_key]
}

The problem is that I am not sure that this code is correct and will avoid deadlock or unsafe thread. Actually debugging my code step by step with breakpoints show me correct results while without breakpoints I have an Array list that contains duplicate elements which shouldn’t happened.


#12

Are you sure that the T1 code is always used to add an entry to the hashtable?
One way to ensure this is to hide the hashtable from public access and provide an indexer property that implements code similar to your T1 and T2.