2

当我将对象缓存到 时HttpContext Cache,我的对象在下一次读取时消失,我必须第二次重新插入该对象(并非总是如此,但 90% 的时间)。在那之后,对象就没有任何问题地呆在那里。

这是发生的事情:

  1. 开始调试mvc项目
  2. 从缓存中读取年龄
  3. 年龄为空,所以我将 50 放入变量中,然后将其插入缓存中
  4. 对客户端的CacheItemRemovedCallback响应完成后立即执行。CacheItemRemovedReason值为_Removed
  5. 用户点击立即刷新
  6. 从缓存中读取年龄
  7. 年龄仍然为空,所以我将 50 放入变量中,然后将其插入缓存中
  8. 用户点击立即刷新
  9. 从缓存中读取年龄
  10. 年龄终于到了!

那么为什么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)
    {
    }
}
4

1 回答 1

3

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

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

全球.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 的 On-Access 扫描程序,hash.web 文件不再更改,因此不会卸载 AppDomain。问题解决了!

有关更多信息,您可以阅读此博客文章

于 2015-02-02T19:24:58.927 回答