Почему я должен дважды поместить свой объект в HttpContext Cache, чтобы он сохранился навсегда?
Когда я кеширую объект в HttpContext Cache
мой объект исчезает при следующем чтении, и я должен повторно вставить объект во второй раз (не всегда, но в 90% случаев). После этого объект останется там без проблем.
Вот что происходит:
- Начните отладку проекта MVC
- Читайте возраст из кеша
- Возраст равен нулю, поэтому я помещаю 50 в переменную и затем вставляю ее в кеш
CacheItemRemovedCallback
выполняется сразу же после ответа клиента.CacheItemRemovedReason
значениеRemoved
- Пользователь нажимает обновить немедленно
- Читайте возраст из кеша
- Возраст по-прежнему нулевой, поэтому я помещаю 50 в переменную, а затем вставляю ее в кеш
- Пользователь нажимает обновить немедленно
- Читайте возраст из кеша
- Эпоха наконец там!
Так почему 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 невозможна. Задача решена!
Для получения дополнительной информации вы можете прочитать этот пост в блоге.