Ленивая инициализация синглтона с параметрами - PullRequest
3 голосов
/ 31 марта 2012

Я пытаюсь создать синглтон с непустым конструктором и получить к нему синхронизированный доступ: поскольку у меня нет контроля над порядком инициализации моего компонента, если компонент обращается к синглтону до его инициализации,он должен ждать.

Метод фабрики вызывается только один раз, и моя фаза инициализации вызывает исключение

private static volatile GottwareExcelAddin _instance;   
private static readonly ManualResetEvent InitializedEvent=new ManualResetEvent(false);

    internal static Singleton CurrentInstance
    {
        get
        {
            InitializedEvent.WaitOne();
            return _instance;
        }
    }

    #endregion

    private Singleton(String url, Int otherstuff)
    {
       // do stuff
        InitializedEvent.Set();
    }


    #region public factory
    [OnWorkerThread]
    public static void Singleton(String spaceUrl, _Application excelApp)
    {
        if (_instance == null)
            _instance = new Singleton(spaceUrl, excelApp);
    }

[OnWorkerThread] - это атрибут, который заставляет фабрику работать на рабочемthread, и фабрика вызывается только один раз.

Когда я запускаю myapp, иногда я получаю следующее:

Источник исключения: mscorlib Тип исключения: System.Runtime.InteropServices.SEHException Сообщение об исключении:Внешний компонент вызвал ошибку исключения.Целевой сайт исключений: WaitOneNative

---- Трассировка стека ---- System.Threading.WaitHandle.WaitOneNative (waitableSafeHandle в качестве SafeHandle, millisecondsTimeout в качестве UInt32, hasThreadAffinity в виде логического значения, exitContext в виде логического выражения) Добавить.dll: N 00000 (0x0) JIT System.Threading.WaitHandle.InternalWaitOne (waitableSafeHandle в качестве SafeHandle, миллисекунды в виде Int64, hasThreadAffinity в виде логического значения, exitContext в виде логического значения) AddinExpress.RTD.2005.dll: N 0020 (0x14).WaitHandle.WaitOne (millisecondsTimeout As Int32, exitContext As Boolean)

Что я делаю не так?

1 Ответ

6 голосов
/ 04 апреля 2012

Вы не создали правильный синглтон там. Правильный синглтон должен иметь статический метод для доступа к нему и закрытый конструктор.

Другая проблема заключается в том, что если у вас есть параметры, с помощью которых можно инициализировать синглтон, что это значит, если вы инициализируете синглтон более одного раза с разными параметрами? Это ошибка?

Предполагая, что вы можете просто игнорировать несколько инициализаций с различными параметрами, вы можете реализовать это следующим образом (но я думаю, что у вас может быть ошибка проектирования где-то):

class Singleton
{
    public static Singleton Instance(string param1, int param2)
    {
        if (_instance == null)
        {
            lock (_locker)
            {
                if (_instance == null) // Double-checked locking (works in C#!).
                {
                    _instance = new Singleton(param1, param2);
                }
            }
        }

        return _instance;
    }

    private Singleton(string param1, int param2)
    {
        // Whatever.
    }

    private static Singleton _instance;
    private static readonly object _locker = new object();
}

Обычно я использую Lazy для реализации синглетонов, но это не очень полезно, если конструктор вашего синглтона требует параметры, переданные в точке доступа вашего синглтона.

...