c# - 在后台线程上初始化单例的常见模式

标签 c# .net multithreading design-patterns singleton

我目前有一个单例,初始化最多可能需要 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 被错误地限定为私有(private)。它应该是公开的并且已经更正。

最佳答案

使用静态构造函数触发它并使用 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();
    }
}

一旦触发事件将保持信号状态,这意味着 Instance 属性将在 Init 方法完成后尽快返回。

关于c# - 在后台线程上初始化单例的常见模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9901003/

相关文章:

c# - 是否可以将 Windows 语言栏设置为英语或从 c# 应用程序恢复为默认设置

c# - 标记界面的目的是什么?

c# - 左外连接代码的列名称不明确

c# - 类总是尝试在设计 View 中打开,而不是代码 View

c# - 是否可以防止 Visual Studio 在 BackgroundWorker.DoWork 内出现异常时中断

c# - 线程只阻塞第一个线程(尝试二)

c# - 等效于 (VB6) IsMissing 在 C# 中?

multithreading - 如何搜索并行化的可能性?

c++ - random_shuffle 线程安全吗?如果不是,则使用 rand_r

c# - Visual Studio 2012 运行 Windows Phone 问题