加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 在背景线程上初始化单例的常用模式

发布时间:2020-12-15 08:18:53 所属栏目:百科 来源:网络整理
导读:我目前有一个单例,初始化最多可能需要10秒.但是,我不希望我的用户对此初始化进行惩罚(等待),因此我宁愿在应用程序启动期间在后台线程上引导此组件.这就是我所拥有的: 辛格尔顿: public class MySingleton{ private static MySingleton _instance; private
我目前有一个单例,初始化最多可能需要10秒.但是,我不希望我的用户对此初始化进行惩罚(等待),因此我宁愿在应用程序启动期间在后台线程上引导此组件.这就是我所拥有的:

辛格尔顿:

public class MySingleton
{
    private static MySingleton _instance;
    private static readonly object _locker = new object();

    private MySingleton() 
    {
        Init();
    }
    public static MySingleton Instance 
    { 
        if(_instance == null) _instance = new MySingleton();
        return _instance;
    }
    public void Init()
    {
        lock(_locker)
        {
            if(_instance != null) return;

            // long running code here...
        }
    }
}

应用程序启动:

Task.Factory.StartNew(() => MySingleton.Instance.Init());

这段代码可以正常工作,防止双初始化,在初始化之前防范用户需要它的边缘情况,并防止有人忘记调用Init().

然而,由于两个原因,它感觉有点笨重:
a)我将在启动时两次进入Init方法.
b)我想在单例内部进行线程化,但必须启动初始化.

是否有更清洁/更好/更好的方法来处理这个?

在此先感谢大家的帮助.

**编辑:正如评论中指出的那样,Init被误认为是私有的.它应该是公开的并且已得到纠正.

解决方法

使用静态构造函数来触发它,并使用ManualResetEvent进行同步.它为您提供了在实际课程中完成所有工作的解决方案.因此,它不依赖于某人应该调用您的init方法.
public class MySingleton
{
    private static MySingleton _instance;
    private static ManualResetEvent _initEvent = new ManualResetEvent(false);

    static MySingleton() 
    {
        ThreadPool.QueueUserWorkItem(state => Init());
    }

    public static MySingleton Instance 
    {
        _initEvent.Wait();
        return _instance;
    }
    private static void Init()
    {
        _instance = new MySingleton();
        // long running code here...


        _initEvent.Set();
    }
}

一旦触发,事件将保持发出信号,这意味着当Init方法完成时,Instance属性将尽快返回.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读