为什么我必须先将对象放在HttpContext Cache中两次才能保持良好状态?

时间:2015-01-30 19:05:17

标签: c# asp.net asp.net-mvc caching httpcontext.cache

当我将对象缓存到HttpContext Cache时,我的对象在下一次读取时消失,我必须再次重新插入对象(并非总是只有90%的时间)。在那之后,对象保持在那里没有任何问题。

发生了什么:

  1. 开始调试mvc项目
  2. 从缓存中读取年龄
  3. 年龄为空所以我在变量中加入了50,然后将其插入缓存中
  4. 当对客户端的响应完成后,CacheItemRemovedCallback立即执行。 CacheItemRemovedReason值为Removed
  5. 用户点击立即刷新
  6. 从缓存中读取年龄
  7. 年龄仍为空所以我在变量中加入了50,然后将其插入缓存中
  8. 用户点击立即刷新
  9. 从缓存中读取年龄
  10. 终于年龄
  11. 那么为什么Cache有问题要将对象保留在第一次插入的缓存中?

    此行为存在于.Net framework 3.5, 4.0, 4.5, 4.5.2

    以下是代码:

    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            int? age = this.HttpContext.Cache.Get("age") as int?;
            if (age == null)
            {
                age = 50;
    
                this.HttpContext.Cache.Add("age", age, null, DateTime.Now.AddHours(5), TimeSpan.Zero, CacheItemPriority.Default, new CacheItemRemovedCallback(this.CacheItemRemovedCallback));
            }
            return View();
        }
    
        public void CacheItemRemovedCallback(String key, Object value, CacheItemRemovedReason reason)
        {
        }
    }
    

1 个答案:

答案 0 :(得分:2)

我的缓存项目在插入后立即删除的原因是因为第一次调用网站后 AppDomain被卸载。通过捕获AppDomain的卸载事件,我已经能够知道关闭原因。 防病毒正在扫描触发FileChangesMonitor AppDomain事件的网站文件,然后触发卸载AppDomain

以下是如何检测AppDomain卸载的原因:

<强> Global.asax中

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);

        AppDomain currentDomain = AppDomain.CurrentDomain;
        currentDomain.DomainUnload += DomainUnloadEventHandler;
    }

    static void DomainUnloadEventHandler(object sender, EventArgs e)
    {
        var httpRuntimeType = typeof(HttpRuntime);

        var httpRuntime = httpRuntimeType.InvokeMember(
            "_theRuntime",
            BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.GetField,
            null, null, null) as HttpRuntime;

        var shutDownMessage = httpRuntimeType.InvokeMember(
            "_shutDownMessage",
            BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField,
            null, httpRuntime, null) as string;

        string shutDownStack = httpRuntime.GetType().InvokeMember(
            "_shutDownStack",
            BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField,
            null, httpRuntime, null) as string;
    }
}

这里是shutDownMessage变量包含的内容:

_shutDownMessage: Change Notification for critical directories.
bin dir change or directory rename
HostingEnvironment initiated shutdown
HostingEnvironment caused shutdown
Change in C:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\root\48a6542f\e317ebf6\hash\hash.web

您是否可以看到, hash.web 文件是AppDomain卸载的原因。现在,谁在改变这个文件?原来是防病毒软件。通过停用McAfee的按访问扫描程序,hash.web文件不再被更改,因此没有AppDomain卸载。问题解决了!

有关详细信息,请参阅此blog post