问题
When i cache an object to the HttpContext Cache
, my object disappear on the next read and I must reinsert the object a second time (not always but 90% of the time). After that, the object stay there without any problem.
Here's what happen:
- Start debugging the mvc project
- Read the age from the cache
- The age is null so i put 50 in the variable and then insert it in the cache
- The
CacheItemRemovedCallback
gets executed immediately when the response to the client is done. TheCacheItemRemovedReason
value isRemoved
- The user click refresh immediately
- Read the age from the cache
- The age is still null so i put 50 in the variable and then insert it in the cache
- The user click refresh immediately
- Read the age from the cache
- The age is there finally!
So why the Cache
have this problem to keep the object in cache on the first insert?
This behavior exist in the .Net framework 3.5, 4.0, 4.5, 4.5.2
.
Here's the code:
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:
The reason why my cached item was removed immediately after his insertion was because the AppDomain get unloaded after the first call to the website. By catching the unload event of the AppDomain
, i've been able to know the shutdown reason. The antivirus was scanning a file of the website that triggered the FileChangesMonitor
event of the AppDomain
that then triggered the unload of the AppDomain.
Here's how to detect the reason why the AppDomain get unloaded :
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;
}
}
Here's what the shutDownMessage
variable contains:
_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
Has you can see, the hash.web file is the cause of the AppDomain unload. Now, who is altering this file? It turns out to be the antivirus. By deactivating the On-Access scanner of McAfee, the hash.web file was not altered anymore so no AppDomain unload. Problem solved!
For further information, you can read this blog post.
来源:https://stackoverflow.com/questions/28242922/why-i-have-to-put-my-object-twice-in-httpcontext-cache-before-it-keep-it-for-goo