我已经实现了一个"自动刷新的MemoryCache"内容通过CacheEntryRemovedCallback。
但是,当从缓存中删除项目时,我遇到阻止脏读的问题。
我的缓存正受到请求的严重影响,我需要确保缓存条目在更新时无法读取。
我的代码如下。正如您所看到的,我尝试在更新缓存以及读取数据时使用简单的lock()。但是,在删除项目并获得锁定的时间内完成了读取。
public List<Domain.Turbine> IgnorableTurbines
{
get
{
var ignorableTurbines = new List<Domain.Turbine>();
lock (ignorableTurbineslockObject)
{
Log.Info("IgnorableTurbines get lock");
Log.Info("Getting ignorable turbines");
ignorableTurbines = (List<Domain.Turbine>)Cache["ignorableturbines"];
}
Log.Info("IgnorableTurbines get released");
return ignorableTurbines;
}
}
void IgnorableStations_CacheItemRemovedCallback(CacheEntryRemovedArguments arguments)
{
lock (ignorableTurbineslockObject)
{
Log.Info("IgnorableTurbines update locked");
Log.InfoFormat("Item removed: {1}", arguments.CacheItem.Key);
var decoupledIgnorableTurbines = _repo.Query<ExcludedStation>().ToList();
AddIgnorableStations("ignorableturbines", decoupledIgnorableTurbines);
Log.Info("IgnorableTurbines re-added");
}
Log.Info("IgnorableTurbines update released");
}
我的日志记录说:
2014-05-20 15:20:45,855 INFO - IgnorableTurbines get lock
2014-05-20 15:20:45,855 INFO - Getting ignorable turbines
2014-05-20 15:20:45,857 INFO - IgnorableTurbines update locked
2014-05-20 15:20:45,863 INFO - Item removed: ignorableturbines
2014-05-20 15:20:45,866 INFO - IgnorableTurbines re-added
2014-05-20 15:20:45,867 INFO - IgnorableTurbines update released
2014-05-20 15:20:45,868 INFO - IgnorableTurbines get released
2014-05-20 15:20:45,871 ERROR - Value cannot be null.
Parameter name: source
System.ArgumentNullException: Value cannot be null.
Parameter name: source
at System.Linq.Queryable.AsQueryable[TElement](IEnumerable`1 source)
at (...).get_IgnorableTurbines()
让我感到困惑的是,锁定&#34;得到&#34;获得并在发布之前锁定&#34;更新&#34;也是。
(我使用log4net进行日志记录)
我做错了什么?
答案 0 :(得分:1)
昨天我想知道我的问题是否是由在删除缓存项后触发的事件引起的,这意味着我试图获取的锁实际上是锁定&#34;没有& #34; - 因此导致&#34;值不能为空&#34;。
所以我挖了一下arround并在Cache中发现了另一个要订阅的事件,结果发现CacheItem对象有一个名为&#34; UpdateCallback&#34;的属性。
所以我改为使用CachEntryUpdateCallback代码,现在一切正常。
现在代码用于更新事件:
void IgnorableStations_CacheItemUpdateCallback(CacheEntryUpdateArguments arguments)
{
Log.Info("Refreshing ignorable stations");
var decoupledIgnorableTurbines =
_repo.Query<ExcludedStation>().Select(i => new Domain.Turbine { StationId = i.WtgNumber, WindfarmId = i.WindFarmId }).ToList();
arguments.UpdatedCacheItem = new CacheItem(arguments.Key, decoupledIgnorableTurbines);
CacheEntryUpdateCallback ignorableStationsCacheItemBeforeUpdateCallback = IgnorableStations_CacheItemUpdateCallback;
arguments.UpdatedCacheItemPolicy = new CacheItemPolicy
{
AbsoluteExpiration = DateTime.Now.AddMinutes(7.00),
UpdateCallback = ignorableStationsCacheItemBeforeUpdateCallback
};
}
初次插入:
void AddIgnorableStations(string key, object ignorableStations)
{
CacheEntryUpdateCallback ignorableStationsCacheItemBeforeUpdateCallback = IgnorableStations_CacheItemUpdateCallback;
var cacheItemPolicy = new CacheItemPolicy
{
AbsoluteExpiration = DateTime.Now.AddMinutes(7.00),
UpdateCallback = ignorableStationsCacheItemBeforeUpdateCallback
};
Cache.Set(key, ignorableStations, cacheItemPolicy);
}