Générer une exception NullReferenceException tout en appelant la set_item méthode d'un objet Dictionary dans un multi-threading scénario

Notre site dispose d'une page de configuration tels que "config.aspx", lorsque la page de l'initialisation va charger quelques informations à partir d'un fichier de configuration. Pour mettre en cache le chargé de l'information, nous avons fourni une usine de classe et nous appelons une méthode publique de l'usine pour obtenir la configuration de l'instance lorsque la page est chargée. Mais parfois, quand le Pool d'Applications est redémarré, nous avons trouvé un message d'erreur dans le Journal des Événements tels que ci-dessous:

De Message: Objet de référence non définie à une instance d'un objet. 
Pile: au Système.Les Collections.Génériques.Dictionnaire`2.Insert(TKey clé, TValue valeur, Boolean add) 
au Système.Les Collections.Génériques.Dictionnaire`2.set_Item(TKey clé, TValue valeur) 
au ObjectFactory.GetInstance(string key) 
à la config.Page_Load(Object sender, EventArgs e) 
au Système.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, l'Objet o, t Objet, EventArgs e) 
au Système.Web.Util.CalliEventHandlerDelegateProxy.Rappel(Object sender, EventArgs e) 
au Système.Web.L'INTERFACE utilisateur.De contrôle.OnLoad(EventArgs e) 
au Système.Web.L'INTERFACE utilisateur.De contrôle.LoadRecursive() 
au Système.Web.L'INTERFACE utilisateur.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) 

L'usine de la classe implémente comme ci-dessous:


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;
    }
} 
 

Je suppose que l'exception a été levée par la ligne "Cas[clé] = instance;", parce que c'est le seul code qui pourrait s'appeler set_Item méthode d'un dictionnaire. Mais si le "Cas" de la valeur est null, il sera jeté une NullReferenceException lors de l'appel de la TryGetValue méthode et le cadre supérieur de la stacktrace devrait être le GetInstance pas le Insert. Personne ne sait comment le dictionnaire pourrait jeter un NullReferenceException lors de l'appel de la set_Item méthode multi-threading scénario?

InformationsquelleAutor Pag Sun | 2009-08-24