【问题标题】:Lazy initialization of a singleton with parameters带参数的单例延迟初始化
【发布时间】:2012-03-31 08:34:10
【问题描述】:

我正在尝试创建一个具有非空构造函数的单例并以同步方式访问它:因为我无法控制组件的初始化顺序,如果组件在初始化之前访问单例,它必须等待。

工厂方法只调用一次,我的初始化阶段抛出异常

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] 是使工厂在工作线程上运行的属性,并且工厂只被调用一次。

当我启动 myapp 时,有时我会得到以下信息:

异常来源:mscorlib 异常类型:System.Runtime.InteropServices.SEHException 异常消息:外部组件已引发异常。 异常目标站点:WaitOneNative

---- 堆栈跟踪 ---- System.Threading.WaitHandle.WaitOneNative(waitableSafeHandle As SafeHandle, millisecondsTimeout As UInt32, hasThreadAffinity As Boolean, exitContext As Boolean) AddinExpress.RTD.2005.dll: N 00000 (0x0) JIT System.Threading.WaitHandle.InternalWaitOne(waitableSafeHandle As SafeHandle, millisecondsTimeout As Int64, hasThreadAffinity As Boolean, exitContext As Boolean) AddinExpress.RTD.2005.dll: N 0020 (0x14) IL System.Threading.WaitHandle.WaitOne(millisecondsTimeout As Int32, exitContext As Boolean)

我做错了什么?

【问题讨论】:

    标签: .net multithreading singleton manualresetevent


    【解决方案1】:

    你还没有在那里创建一个合适的单例。一个合适的单例应该有一个静态方法来访问它,以及一个私有构造函数。

    另一个问题是,如果您有用于初始化单例的参数,那么如果您使用不同的参数多次初始化单例,这意味着什么?这是一个错误吗?

    假设您可以忽略具有不同参数的多个初始化,您可以按如下方式实现它(但我认为您可能在某处有设计错误):

    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 来实现单例,但如果单例的构造函数需要在单例的访问点传入参数,它就没有那么有用了。

    【讨论】:

    • 对不起...我想要做的是用我的代码中的一点(在启动时)的参数初始化单例。但是,由于 Excel 组件的初始化顺序(例如,如果您通过双击电子表格启动 Excel),其他组件可能首先被初始化并尝试访问单例。我希望这些等到主组件初始化单例...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-01
    • 2020-05-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多