我已经实现了一个 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()
令我困惑的是,获得了“获取”锁定,并且在释放之前还获得了“更新”锁定。
(我正在使用 log4net 进行日志记录)
我究竟做错了什么?