添加对象后,MemoryCache为空

时间:2011-10-21 11:52:00

标签: asp.net-mvc c#-4.0

我在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不存在,因此我得到了Exception。

我在Cassini和IIS 7上测试这个,它似乎与AppPool可重用性无关(在IIS 7中启用),我已经测试了几个缓存策略,但无法使其工作

我错过了什么/失败了什么?

PS:原谅我的英语不好

3 个答案:

答案 0 :(得分:3)

使用decomplier查看MemoryCache的代码,有以下私有函数

private void OnUnhandledException(object sender, UnhandledExceptionEventArgs eventArgs)
{
  if (!eventArgs.IsTerminating)
    return;
  this.Dispose();
}

每个MemoryCache都为当前域Thread.GetDomain()设置了一个未处理的异常处理程序,因此,如果您的应用程序中没有任何异常处理,这可能在网站中很常见,它会永远处理MemoryCache无法重复使用这与IIS应用程序特别相关,因为Windows应用程序只是在无法处理的例外情况下退出。

答案 1 :(得分:1)

MemoryCache 的大小有限。对于Default实例,不是启发式值(根据MSDN)。

您是否尝试将 CacheItemPolicy 实例上的优先级属性设置为 NotRemovable

您可以拥有竞争条件,因为 SetLoginInfo 中的Contains-Remove-Add序列不是原子的 - 请尝试使用Set方法。

顺便说一下。您正在处理Web应用程序,那么为什么不使用System.Web.Caching.Cache呢?

答案 2 :(得分:1)

我相信你遇到了一个Scott Hanselman认定为.NET 4漏洞的问题。请看这里:MemoryCache Empty : Returns null after being set