Why i have to put my object twice in HttpContext Cache before it keep it for good?

875 Views Asked by At

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:

  1. Start debugging the mvc project
  2. Read the age from the cache
  3. The age is null so i put 50 in the variable and then insert it in the cache
  4. The CacheItemRemovedCallback gets executed immediately when the response to the client is done. The CacheItemRemovedReason value is Removed
  5. The user click refresh immediately
  6. Read the age from the cache
  7. The age is still null so i put 50 in the variable and then insert it in the cache
  8. The user click refresh immediately
  9. Read the age from the cache
  10. 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

There are 1 best solutions below

0
On BEST ANSWER

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.