C# 如何在不等待的情况下在单例中执行昂贵的操作?

C# 如何在不等待的情况下在单例中执行昂贵的操作?,c#,.net,singleton,lazy-loading,C#,.net,Singleton,Lazy Loading,我创建了一个单例模式的类,其中包含一些实例变量(字典),填充起来非常昂贵 此类用于.NETMVC4项目中。它们的关键在于,这个单例类中字典提供的数据很好,但web应用程序不需要运行 换句话说,当我们处理一个web请求时,如果字典中的信息可用,请求将得到增强,但如果字典中的信息不可用,则可以 因此,我想做的是找到最好的方法,将数据加载到Singleton中的这些字典中,而不阻塞web活动,因为它们充满了数据 我通常会用多线程来实现这一点,但在过去,我读过关于ASP.NET中使用多线程技术的文章,并

我创建了一个单例模式的类,其中包含一些实例变量(字典),填充起来非常昂贵

此类用于.NETMVC4项目中。它们的关键在于,这个单例类中字典提供的数据很好,但web应用程序不需要运行

换句话说,当我们处理一个web请求时,如果字典中的信息可用,请求将得到增强,但如果字典中的信息不可用,则可以

因此,我想做的是找到最好的方法,将数据加载到Singleton中的这些字典中,而不阻塞web活动,因为它们充满了数据

我通常会用多线程来实现这一点,但在过去,我读过关于ASP.NET中使用多线程技术的文章,并遇到了一些问题。在.NET4/MVC4中,情况发生了变化吗?我应该如何处理这个问题

更新

根据下面的反馈和,我现在正在做的事情如下所示,它似乎工作得很好。有人看到任何潜在的问题吗?在我的测试中,无论我调用LazySingleton.Instance多少次,构造函数只被调用一次,并立即返回。我可以立即访问LazySingleton.priced_缓存,尽管它可能不包含我正在查找的值(我在我的应用程序中使用
.Contains()
call进行测试)。所以它似乎在起作用

如果我只从一个线程(LazySingleton构造函数)编辑昂贵的_缓存字典,那么在我的web应用程序中读取它时是否需要担心线程安全

public class LazySingleton
{
    public ConcurrentDictionary<string, string> EXPENSIVE_CACHE = new ConcurrentDictionary<string, string>(1, 80000); // writing to cache in only one thread
    private static readonly Lazy<LazySingleton> instance = new Lazy<LazySingleton>(() => new LazySingleton());

    private LazySingleton()
    {
        Task.Factory.StartNew(() => expensiveLoad());
    }

    public static LazySingleton Instance
    {
        get
        {
            return instance.Value;
        }
    }

    private void expensiveLoad()
    {
        // load data into EXPENSIVE_CACHE
    }
}
公共类懒汉
{
public ConcurrentDictionary\u CACHE=new ConcurrentDictionary(1,80000);//仅在一个线程中写入缓存
private static readonly Lazy instance=new Lazy(()=>new LazySingleton());
私人懒汉()
{
Task.Factory.StartNew(()=>expensiveLoad());
}
公共静态LazySingleton实例
{
得到
{
返回instance.Value;
}
}
私人无效费用()
{
//将数据加载到高速缓存中
}
}

您可以使用以下任何一种方式填充您的现金存储库:

  • 应用程序启动
  • 会话(u)开始
  • 您的web应用程序事件。
    像这样的

    <%@ Application Language="C#" %>
    <script runat="server">
        void Application_Start(object sender, EventArgs e) 
        {
            SingletonCache.LoadStaticCache();
        }
    </script>
    
    
    无效应用程序\u启动(对象发送方,事件参数e)
    {
    SingletonCache.LoadStaticCache();
    }
    

    可能很有用

    所以你在问如何用值延迟加载字典?如果它不可用,那没关系-那么你就不必这么做;]单例与问题相关吗?@Tejs是的,但在.NET MVC 4的特定上下文中。@bas我不确定它是否相关。以前,我们使用静态构造的对象来保存此类信息,直到最近才转向单例模式,以便在ASP.NET环境之外安全地工作。我很感谢您的响应。但是,在缓存加载完成之前,这不会阻止应用程序完成启动吗?在这种情况下,它会阻止对web应用程序的第一次响应,直到它完成?您将不得不支付一次兑现的代价。为了充分保证应用程序的完整性,我不喜欢异步解决方案,可能使用数据库或序列化解决方案来保存现金字典会降低成本。我想这就是问题所在。。。我希望使用异步,因为在这种情况下,我真的不需要在应用程序运行之前加载数据。只是,如果数据可用,很高兴参考它。好吧,这就是我计划去的地方,但在过去,我在ASP.NET中合并多线程时遇到了问题,并且在过去被烧掉了,我只是远离它。。。不知道情况是否有所改善。(很多时间过去了。)我认为使用应用程序启动和线程池将是一个安全的解决方案,朋友,请尝试并通知我。