Throw a NullReferenceException while calling the set_item method of a Dictionary object in a multi-threading scenario
Solution 1:
As the exception occurs internally in the Dictionary
code, it means that you are accessing the same Dictionary
instance from more than one thread at the same time.
You need to synchronise the code in the GetInstance
method so that only one thread at a time accesses the Dictionary
.
Edit:
Lock around the accesses separately, so that you aren't inside a lock while doing the (supposedly) time consuming loading:
private static object _sync = new object();
public static object GetInstance(string key) {
object instance = null;
bool found;
lock (_sync) {
found = Instances.TryGetValue(key, out instance);
}
if (!found) {
instance = LoadInstance(key);
lock (_sync) {
object current;
if (Instances.TryGetValue(key, out current)) {
// some other thread already loaded the object, so we use that instead
instance = current;
} else {
Instances[key] = instance;
}
}
}
return instance;
}
Solution 2:
As of .Net 4 you have ConcurrentDictionary which is a thread-safe dictionary, no more need for "manual" synchronization.
Solution 3:
To quote http://msdn.microsoft.com/en-us/library/xfhwa508.aspx (emphasis added by me):
"Thread Safety
Public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.
A Dictionary<(Of <(TKey, TValue>)>)
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."
Solution 4:
I think your Instances
Dictionary
is not null. Your exception is from inside the Insert
method - meaning that there is a Dictionary
object at runtime (Also, as you've said, you have already had TryGetValue
before, on the same reference)
Could it be that your key
is null?
EDIT
Just checked it - TryGetValue
throws ArgumentNullException when it receives a null key, and so does insert with a null key. But what class are you using in your example? I used the generic IDictionary<string, string>
, but I see you are using a non generic one. Is it a class you have inherited from DictionaryBase
or maybe HashTable
?