停止缓存的双重加载
Stop double loading of cache
给出从数据库加载所有可用语言的代码(仅用作示例):
/// <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];
}
如果将记录加载到缓存中的代码需要一段时间才能完成,并且有另一个页面请求进来,它会抛出异常并导致一些问题。
修改上述代码以使其安全应对这种情况的最佳方法是什么?
您可以使用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);
您必须使用 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];
}
给出从数据库加载所有可用语言的代码(仅用作示例):
/// <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];
}
如果将记录加载到缓存中的代码需要一段时间才能完成,并且有另一个页面请求进来,它会抛出异常并导致一些问题。
修改上述代码以使其安全应对这种情况的最佳方法是什么?
您可以使用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);
您必须使用 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];
}