如何在单个线程中使缓存的值无效?

时间:2017-07-04 04:10:26

标签: c# asp.net caching

我使用Http.Current.Cache存储从我的数据库中检索的各种值,因为我的应用程序是数据密集型的。在我的新笔记本电脑上使用VS2017安装运行我的网站时(在VS2015的另一台笔记本电脑上,我从未见过这个问题),我看到一个非常奇怪的问题,其中缓存的值似乎被随机清除 - 几乎是以违反逻辑的方式。

例如,我有一个 if 子句,其条件是所讨论的缓存项不为null。我的代码肯定是通过这个 if 语句的路径,但稍后调试器显示缓存项实际上是空的 - 导致我的应用程序失败。

public static SportSeason GetCurrentSportSeason(string sportCode)
{
  SportSeason sportSeason = null;
  string key = "Sheets_SportSeason_" + sportCode;

  int i = 0;
  if (BaseSheet.Settings.EnableCaching && BizObject.Cache[key] != null)
  {
    i = 1;
    sportSeason = (SportSeason)BizObject.Cache[key];
  }
  else
  {
    i = 2;
    sportSeason = GetSportSeasonFromSportSeasonDetails(SiteProvider.Sheets.GetCurrentSportSeason(sportCode));
    BaseSheet.CacheData(key, sportSeason);
  }
  if(sportSeason == null)
  {
    int j = i;
  }
  return sportSeason;
}

我可以在final if中设置断点,并且变量i设置为1,但sportSeason对象为NULL(缓存条目也是如此)。如果缓存项不为空,代码进入第一个 if 子句的唯一方法是什么呢?

这是一个屏幕截图,显示了一些在最终if。enter image description here

中带有断点的监视变量

这很难追查,因为它在我的业务对象中随机发生。有时候,在看到这个问题之前,我必须刷新页面3到4次。

如何快速地使缓存失效,以及通过什么?屏幕截图显示缓存项目不多,所以我不认为我的内存不足。并且没有其他进程正在运行,这可能会破坏缓存。

编辑:通过更多调试,我确定只有在断点处再次检查时,才会清除第91行上检查的缓存键(设置为空)。所有其他缓存记录仍然存在。

EDIT2:我已将问题归结为此问题,尽管它仍然似乎无视逻辑:

    HttpContext.Current.Cache.Insert("ABC", "123", null, DateTime.Now.AddSeconds(600), TimeSpan.Zero);
    int i = 0;

我清除了所有缓存。当我跳过Cache.Insert语句时,我的缓存计数变为1.但是,根据该键的缓存项目保持为空(请参阅监视窗口)。

enter image description here

另外,如果我再执行一个语句(int i = 0),缓存计数会回到零。

enter image description here

Edit3:这是杀死我的Insert()的AbsoluteExpiration参数。时钟已关闭。

如果我将AbsoluteExpiration设置为未来5小时(300分钟),则无效。如果我将它设置为将来的5小时1分钟(301分钟),一切正常。

    HttpContext.Current.Cache.Insert("ABC", "123", null, DateTime.Now.AddMinutes(301), TimeSpan.Zero);

我的笔记本电脑上的时钟是100%准确的,您可以看到Intellisense也显示正确的时间。缓存是否可以基于5小时的其他时钟?

enter image description here

Edit4:看起来像someone else is off by 5 hours

3 个答案:

答案 0 :(得分:7)

修复是在指定AbsoluteExporation参数时始终使用DateTime。 Utc 现在而不是DateTime.Now。

这样做:

react-native-cli

不是这个:

HttpContext.Current.Cache.Insert("ABC", "123", null, DateTime.UtcNow.AddMinutes(1), System.Web.Caching.Cache.NoSlidingExpiration);

当我这样做时,它正确识别缓存是有效的,我可以检索该值。至于为什么在我的Windows 10 Pro笔记本电脑上需要这个,而不是在我的Windows 10 Home上,我不知道。

答案 1 :(得分:2)

您可以添加一个回调函数,该函数可以告诉您项目被删除的原因:

https://msdn.microsoft.com/en-us/library/7kxdx246.aspx

您在添加项目时指定回调,并在删除项目时触发。在其中放置断点或记录输出以打印出CacheItemRemovedReason参数。

如果这对您没有帮助,您可以尝试在ASP.NET HttpContext Cache removes right after insertion的最佳答案中列出的调试步骤。如果应用程序正在终止,这可能会被捕获。

答案 2 :(得分:0)

检查IIS应用程序池回收选项以排除回收事件。因为application pool recycle, will clear your cache

Per the App pool recycling settings docs

  

您可以指定IIS以设置的时间间隔回收应用程序池   (例如每180分钟),在每天的特定时间或之后   应用程序池收到一定数量的请求。你也可以   配置元素以在何时重新启动应用程序池   工作进程虚拟内存和物理内存使用量达到了   具体门槛。

即使更改配置也可以回收应用池。

确保没有其他应用共享您的应用池,然后启用回收日志并重现问题。查看缓存消失是否与日志中的应用程序池回收相关联。如果是这样,请从那里确定回收发生的原因,然后进行配置更改,以便app pool在正常工作时间内不会回收。