J'ai passé environ une heure à chercher un consensus sur quelque chose que j'essaie d'accomplir, mais je n'ai pas encore trouvé quelque chose de concluant dans une direction particulière.Threadsafe chargement paresseux lorsque le chargement pourrait échouer
Ma situation est la suivante:
- J'ai une application multi-thread (service Web .NET)
- J'ai des classes qui utilisent des objets qui prennent du temps non négligeable à la charge, donc je comme pour les maintenir en tant que membres statiques de classe
- Le code qui construit ces objets a par intermittence un faible risque d'échec
j'utilisais déjà une approche qui construit ces objets dans un constructeur statique. Le problème avec ceci était que, comme mentionné ci-dessus, le constructeur échouait parfois, et une fois qu'un constructeur statique de .NET échoue, la classe entière est arrosée jusqu'à ce que le processus soit relancé. Il n'y a pas de seconde chance avec cette approche.
L'approche qui semblait la plus intuitive était d'utiliser le verrouillage à double contrôle. Il y a beaucoup de pages autour de cette discussion sur les inconvénients du verrouillage à double vérification et dire d'utiliser un constructeur statique, ce que je faisais déjà, mais cela ne semble pas être une option pour moi, car le constructeur statique a le potentiel d'échouer et de faire tomber toute la classe.
La mise en œuvre (simplifiée, bien sûr) que je songe à utiliser est la suivante. Tous les noms de classe et de membre sont purement démonstratifs et pas ce que j'utilise réellement. Cette approche va-t-elle poser problème? Quelqu'un peut-il suggérer une meilleure approche?
public class LazyMembers
{
private static volatile XmlDocument s_doc;
private static volatile XmlNamespaceManager s_nsmgr;
private static readonly object s_lock = new object();
private static void EnsureStaticMembers()
{
if (s_doc == null || s_nsmgr == null)
{
lock (s_lock)
{
if (s_doc == null || s_nsmgr == null)
{
// The following method might fail
// with an exception, but if it succeeds,
// s_doc and s_nsmgr will be initialized
s_doc = LoadDoc(out s_nsmgr);
}
}
}
}
public XmlNamespaceManager NamespaceManager
{
get
{
EnsureStaticMembers();
return s_nsmgr;
}
}
public XmlDocument GetDocClone()
{
EnsureStaticMembers();
return (XmlDocument)s_doc.Clone();
}
}
Problèmes de verrouillage par double vérification dans .NET? Citation? –
C'était l'article de Jon Skeets qui ressortait le plus, mais j'ai vu beaucoup d'articles et de discussions ici et là disant que personne ne sait vraiment si c'est sûr sur C# et/ou de ne pas l'utiliser entièrement. Je n'ai encore vu personne en fait recommander l'utilisation sur .NET. – Jimmy
Je pense que Jon a fait une analyse très décente. Cela fonctionne mais des mots comme «modèle de mémoire» en combinaison avec «version de plate-forme» devraient vous effrayer. –