Почему я должен дважды поместить свой объект в HttpContext Cache, чтобы он сохранился навсегда?

Когда я кеширую объект в 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)
    {
    }
}

1 ответ

Решение

Причина, по которой мой кэшированный элемент был удален сразу после его вставки, заключалась в том, что 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 невозможна. Задача решена!

Для получения дополнительной информации вы можете прочитать этот пост в блоге.

Другие вопросы по тегам