【发布时间】:2011-12-12 12:51:48
【问题描述】:
我在 MVC 3 ASP.NET 应用程序中遇到了一个奇怪的 ASP.NET MemoryCaching 问题。
每次执行一个动作,我都会检查它的LoginInfo是否真的存储在MemoryCache中(代码已经简化,但核心如下):
[NonAction]
protected override void OnAuthorization(AuthorizationContext filterContext) {
Boolean autorizzato = false;
LoginInfo me = CacheUtils.GetLoginData(User.Identity.Name);
if (me == null)
{
me = LoginData.UserLogin(User.Identity.Name);
CacheUtils.SetLoginInfo(User.Identity.Name, me);
}
// Test if the object is really in the memory cache
if (CacheUtils.GetLoginData(User.Identity.Name) == null) {
throw new Exception("IMPOSSIBLE");
}
}
GetLoginInfo 是:
public static LoginInfo GetLoginData(String Username)
{
LoginInfo local = null;
ObjectCache cache = MemoryCache.Default;
if (cache.Contains(Username.ToUpper()))
{
local = (LoginInfo)cache.Get(Username.ToUpper());
}
else
{
log.Warn("User " + Username + " not found in cache");
}
return local;
}
SetLoginInfo 是:
public static void SetLoginInfo (String Username, LoginInfo Info)
{
ObjectCache cache = MemoryCache.Default;
if ((Username != null) && (Info != null))
{
if (cache.Contains(Username.ToUpper()))
{
cache.Remove(Username.ToUpper());
}
cache.Add(Username.ToUpper(), Info, new CacheItemPolicy());
}
else
{
log.Error("NotFound...");
}
}
代码非常简单,但有时(完全随机),在将 LoginInfo 添加到 MemoryCache 之后,结果为空,刚刚添加的 Object 不存在,因此我得到了异常。
我在 Cassini 和 IIS 7 上都对此进行了测试,它似乎与 AppPool 可重用性(在 IIS 7 中启用)无关,我已经测试了多个缓存策略,但无法使其工作
我错过了什么/失败了?
PS:原谅我的英语不好
【问题讨论】:
-
你有没有一个叫
GetLoginInfo和GetLoginData的方法,或者这是一个错字? -
您确认
LoginData.UserLogin(User.Identity.Name);没有返回空值吗? -
@DannyTuppeny:setter/getter 的不同名称是我的剪切粘贴中的错字。 UserLogin 方法不返回 null,它从数据库表中读取用户配置文件,顺便说一句,通过检查所有变量进行交叉检查。我怀疑我在缓存中的条目在我添加它之后就被某些东西处理了。将尝试添加 RemoveCallback 以查看是否是这种情况。
-
@BigMike,看起来
MemoryCache.Default是进程范围的。你确定你没有遇到两个线程之间的竞争情况吗?例如,Get()可能发生在线程 B 上的Remove()和Add()之间的线程 A 上。 -
@FrédéricHamidi 没有考虑过这种情况,可能是一个很好的见解。实际上应用程序在 ASP.NET 应用程序池中运行(如果他们没有更改它,应该是同一个 IIS 进程的线程池)。明天我一回来工作,我就会调查这件事。谢谢。
标签: asp.net-mvc c#-4.0