Я потратил около часа в поисках консенсуса на то, что я пытаюсь выполнить, но мне еще не удалось найти что-то убедительное в определенном направлении.
Моя ситуация такова:
- У меня есть многопоточное приложение (веб-служба .NET)
- У меня есть классы, которые используют объекты, для загрузки которых требуется ничтожное время, поэтому я бы хотел сохранить их как статическиечлены класса
- Код, который создает эти объекты периодически, имеет низкую вероятность сбоя
Ранее я использовал подход, который создает эти объекты в статическом конструкторе.Проблема с этим заключалась в том, что, как упоминалось выше, конструктор иногда выходил из строя, и как только статический конструктор .NET терпел неудачу, весь класс оставался в стороне до тех пор, пока процесс не будет перезапущен.Второго шанса при таком подходе нет.
Наиболее интуитивно-понятный подход после этого заключался в использовании двойной проверки блокировки.Вокруг есть много страниц, которые рассказывают о пороках двойной проверки блокировки и говорят, что я использую статический конструктор, что я уже делал, но это не вариант для меня, так как статический конструктор имеетвозможность провалиться и обрушить весь класс.
Реализация (конечно, упрощенная), которую я думаю использовать, заключается в следующем.Все имена классов и членов носят чисто демонстрационный характер, а не то, что я на самом деле использую.Этот подход будет проблематичным?Кто-нибудь может предложить лучший подход?
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();
}
}