停止双重加载缓存

时间:2015-08-06 12:50:58

标签: c# asp.net caching locking

鉴于此代码从数据库加载所有可用语言(仅用作示例):

/// <summary>
/// Dictionary of all languages
/// </summary>
private static Dictionary<int, Language> GetLanguagesDictionary()
{
    const string cacheIndex = Settings.CachePrefix + "LanguagesDictionary";
    var context = HttpContext.Current;
    if (context.Cache[cacheIndex] == null)
    {
        var dict = new Dictionary<int, Language>();
        using (var db = new DBContext())
        {
            var q = db.Languages;
            foreach (var rec in q)
            {
                dict.Add(rec.ID, new Language(rec));
            }
        }
        context.Cache.Add(cacheIndex, dict, null, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.Normal, null);
    }
    return (Dictionary<int, Language>) context.Cache[cacheIndex];
}

如果将记录加载到缓存中的代码需要一段时间才能完成并且另一个页面请求进入,它会抛出异常并导致一些问题。

修改上述代码的最佳方法是什么?以防止出现这种情况?

2 个答案:

答案 0 :(得分:1)

您可以使用Lazy<T>

static Lazy<Dictionary<int, Language>> GetLanguage = 
      new Lazy<Dictionary<int, Language>>(() => GetLanguagesDictionary(), true);

现在,您将在代码中使用GetLanguage.Value

<强>更新

您的最终代码与此类似:

private static Dictionary<int, Language> GetLanguagesDictionary()
{
        var dict = new Dictionary<int, Language>();
        using (var db = new DBContext())
        {
            var q = db.Languages;
            foreach (var rec in q)
            {
                dict.Add(rec.ID, new Language(rec));
            }
        }
        return dict;
}

public static Lazy<Dictionary<int, Language>> GetLanguages = 
    new Lazy<Dictionary<int, Language>>(() => GetLanguagesDictionary(), true);

答案 1 :(得分:0)

您必须使用lock将缓存的写入和创建同步为:

///
/// for locking synhronize
///
private static readonly object syncLock = new object();

/// <summary>
/// Dictionary of all languages
/// </summary>
private static Dictionary<int, Language> GetLanguagesDictionary()
{
    const string cacheIndex = Settings.CachePrefix + "LanguagesDictionary";
    var context = HttpContext.Current;

    if (context.Cache[cacheIndex] == null)
    {
        lock (syncLock)
        {
            if (context.Cache[cacheIndex] == null)
            {
                var dict = new Dictionary<int, Language>();
                using (var db = new DBContext())
                {
                    var q = db.Languages;
                    foreach (var rec in q)
                    {
                        dict.Add(rec.ID, new Language(rec));
                    }
                }
                context.Cache.Add(cacheIndex, dict, null, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.Normal, null);
            }
        }
    }
    return (Dictionary<int, Language>)context.Cache[cacheIndex];
}