На нашем веб-сайте есть страница конфигурации, такая как «config.aspx», когда при инициализации страницы загружается некоторая информация из файла конфигурации. Для кэширования загруженной информации мы предоставили фабричный класс и вызываем открытый метод фабрики, чтобы получить экземпляр конфигурации при загрузке страницы. Но иногда, когда пул приложений перезапускается, в журнале событий обнаруживается сообщение об ошибке, например ниже:
Message: Object reference not set to an instance of an object.
Stack: at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
at System.Collections.Generic.Dictionary`2.set_Item(TKey key, TValue value)
at ObjectFactory.GetInstance(string key)
at config.Page_Load(Object sender, EventArgs e)
at System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e)
at System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e)
at System.Web.UI.Control.OnLoad(EventArgs e)
at System.Web.UI.Control.LoadRecursive()
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
Класс фабрики реализует как показано ниже:
public static class ObjectFactory
{
private static object _InternalSyncObject;
private static Dictionary _Instances;
private static object InternalSyncObject
{
get
{
if (_InternalSyncObject == null)
{
var @object = new object();
Interlocked.CompareExchange(ref _InternalSyncObject, @object, null);
}
return _InternalSyncObject;
}
}
private static Dictionary Instances
{
get
{
if (_Instances == null)
{
lock (InternalSyncObject)
{
if (_Instances == null)
{
_Instances = new Dictionary();
}
}
}
return _Instances;
}
}
private static object LoadInstance(string key)
{
object obj = null;
// some statements to load an specific instance from a configuration file.
return obj;
}
public static object GetInstance(string key)
{
object instance;
if (false == Instances.TryGetValue(key, out instance))
{
instance = LoadInstance(key);
Instances[key] = instance;
}
return instance;
}
}
Я предполагаю, что исключение было выдано строкой "Instances [key] = instance;", потому что это единственный код, который может вызывать set_Item
метод словаря. Но если значение «Экземпляры» равно нулю, при вызове метода TryGetValue
оно выдает NullReferenceException
, а верхний кадр трассировки стека должен быть GetInstance
, а не Insert
. Кто-нибудь знает, как словарь может выдавать NullReferenceException
при вызове метода set_Item
в многопоточном сценарии?