有啥方法可以清除/刷新/删除OutputCache?

Posted

技术标签:

【中文标题】有啥方法可以清除/刷新/删除OutputCache?【英文标题】:Any way to clear/flush/remove OutputCache?有什么方法可以清除/刷新/删除OutputCache? 【发布时间】:2009-02-19 13:07:08 【问题描述】:

我在我的网络用户控件 (.ascx) 上使用 OutputCache

<%@ OutputCache Duration="1000" VaryByParam="none" %>

我想在接下来的 1000 秒内保留缓存,但是当我网站上的特定页面被加载时,我想删除/刷新/刷新缓存。比如,我想在加载 MyPage.aspx 时清除缓存。我可以通过编程方式刷新缓存吗?

它只有一页被缓存,因此没有参数化版本可以刷新缓存。

提前感谢您的帮助。

【问题讨论】:

【参考方案1】:

您可以为此使用VaryByCustom 参数。

在您的用户控件中,您将拥有以下内容:

<%@ OutputCache Duration="1000" VaryByParam="None" VaryByCustom="MyKey" %>

然后您将覆盖 Global.asax 中的 GetVaryByCustomString 方法,如下所示:

public override string GetVaryByCustomString(HttpContext context, string arg)

    if (arg == "MyKey")
    
        object o = context.Current.Application["MyGuid"];
        if (o == null)
        
            o = Guid.NewGuid();
            context.Current.Application["MyGuid"] = o;
        
        return o.ToString();
    
    return base.GetVaryByCustomString(context, arg);

最后在MyPage.aspx 你会这样做:

Application["MyGuid"] = Guid.NewGuid();

这是如何工作的?

当你的控件被缓存时,它与一个字符串相关联(当你的控件的VaryByCustom 键被传递给它时,从GetVaryByCustomString 方法返回的字符串)。

每当随后使用该控件时,都会再次调用GetVaryByCustomString。如果返回的字符串与控件的缓存版本匹配,则使用缓存版本。

在我们的例子中,“MyKey”被传递到GetVaryByCustomString 并返回存储在Application["MyGuid"] 中的任何内容。

每当调用MyPage.aspx 时,它都会将Application["MyGuid"] 更改为一个新的随机值。

下次使用您的控件时,GetVaryByCustomString 方法将返回新值,并且由于没有与该值关联的控件的缓存版本,因此将重新生成控件。 (然后控件将被缓存并与新值相关联,直到下一次调用 MyPage.aspx 等)

有一个概述here。

【讨论】:

是删除之前的副本还是保留2个? 这实际上并没有从缓存中清除任何东西,只是添加了一个新的唯一键,看起来像是一个清除缓存,所以是的,现在内存中会有两个缓存数据的副本。如果您已经在网站的其他地方使用 VaryByCustom,您可能需要修改上述代码以将 GUID 附加到现有的 VaryByCustom 字符串。 此方法成功。感谢您的提示。干得好。【参考方案2】:

您可以使用HttpResponse.RemoveOutputCacheItemHttpResponse.AddCacheItemDependency 使输出缓存条目无效。

【讨论】:

我最终做了类似的事情:***.com/questions/11585/… 如果您的 OutputCacheProvider 不是默认值(例如,您使用的是 AppFabric 或 MemCached)这些方法将不起作用。只是提醒任何考虑他们的选择的人......我认为 VaryByCustom 答案更可取,因为它适用于任何一种情况。 真的两者都可取; VaryByCustom 可以为您提供他所询问的一些内容,但如果页面的先前版本真的永远死了,再也不会被使用,您可能会通过使用 RemoveOutputCacheItem 显式驱逐它来减少缓存压力。【参考方案3】:

破解一种疯狂的方法有点像大锤,但它是完全清除/刷新我发现的应用程序缓存的最简单和最有效的方法。

只需调用:

HttpRuntime.UnloadAppDomain();

这与回收应用程序池具有相同的影响。并非在所有情况下都适用,但它肯定会完成工作。

【讨论】:

我同意。在用尽了许多不同的技术之后,这是唯一可靠的工作方法。 这根本不是清除缓存的唯一可靠方法。这意味着其他机制都不起作用,这是大胆的。卸载应用程序域非常繁琐。【参考方案4】:

编辑:如果您在 II6+ 上启用了内核缓存,那么您将需要遵循 Luke 的建议并使用 VaryByCustom 标头,因为清除 ASP.NET 缓存不会影响内核缓存。

OutputCache 存储在 ASP.NET Cache 中,因此您只需调用 Cache.Remove:

List<string> keys = new List<string>();

foreach(string key in HttpRuntime.Cache)

    keys.Add(key);


foreach(string key in keys)

    Cache.Remove(key);

但是,这将删除所有缓存条目,包括您的代码添加的自定义条目。

【讨论】:

你确定这是同一个缓存吗?我认为 OutputCache 是 IIS 的东西。我认为这行不通。 在 IIS7 中默认启用内核缓存:technet.microsoft.com/en-us/library/cc731903(v=ws.10).aspx 因此,如果您从未配置过此功能,则已启用它。 这只会删除自定义缓存项目,而不是缓存的网址/页面。【参考方案5】:

受其他帖子的启发,下面的 sn-p 使用反射成功删除了 asp.net 中OutputCache 缓存的每个页面:

        public static void ClearOutputCache()
        

            var runtimeType = typeof(HttpRuntime);

            var ci = runtimeType.GetProperty(
               "CacheInternal",
               BindingFlags.NonPublic | BindingFlags.Static);

            var cache = ci.GetValue(ci, new object[0]);

            var cachesInfo = cache.GetType().GetField(
                "_caches",
                BindingFlags.NonPublic | BindingFlags.Instance);
            var cacheEntries = cachesInfo.GetValue(cache);

            var outputCacheEntries = new List<object>();

            foreach (Object singleCache in cacheEntries as Array)
            
                var singleCacheInfo =
                singleCache.GetType().GetField("_entries",
                   BindingFlags.NonPublic | BindingFlags.Instance);
                var entries = singleCacheInfo.GetValue(singleCache);

                foreach (DictionaryEntry cacheEntry in entries as Hashtable)
                
                    var cacheEntryInfo = cacheEntry.Value.GetType().GetField("_value",
                       BindingFlags.NonPublic | BindingFlags.Instance);
                    var value = cacheEntryInfo.GetValue(cacheEntry.Value);
                    if (value.GetType().Name == "CachedRawResponse")
                    
                        var key = (string)cacheEntry.Value.GetType().BaseType.GetField("_key", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(cacheEntry.Value);
                        key = key.Substring(key.IndexOf("/"));
                        outputCacheEntries.Add(key);
                    
                
            
            foreach (string key in outputCacheEntries)
              
                HttpResponse.RemoveOutputCacheItem(key);
            
        

【讨论】:

这个答案对我帮助很大。能够遍历缓存并获取密钥向我展示了我所需要的。谢谢。 我尝试使用代码,但出现运行时错误 System.NullReferenceException: var cacheEntries = cachesInfo.GetValue(cache);【参考方案6】:

由于this answer 不再起作用,并且this answer 仅清除自定义缓存项(而不是缓存中存储的页面/MVC 操作),我挖掘了 ASP.NET 参考源代码并得出了以下结论:

public static void ClearAllCache()

    var runtimeType = typeof(System.Web.Caching.Cache);

    var ci = runtimeType.GetProperty(
       "InternalCache",
       BindingFlags.Instance | BindingFlags.NonPublic);

    var cache = ci.GetValue(HttpRuntime.Cache) as System.Web.Caching.CacheStoreProvider;
    enumerator = cache.GetEnumerator();
    while (enumerator.MoveNext())
    
        keys.Add(enumerator.Key.ToString());
    
    foreach (string key in keys)
    
        cache.Remove(key);
    

更多信息在我的博文here

【讨论】:

【参考方案7】:

您可以添加 HttpResponse.RemoveOutputCacheItem("/YourCachePageName.aspx");页面的页面加载事件中的代码行,您希望缓存页面的缓存关闭。

【讨论】:

以上是关于有啥方法可以清除/刷新/删除OutputCache?的主要内容,如果未能解决你的问题,请参考以下文章

IIS(动态和静态)缓存、OutPutCache 和浏览器缓存有啥区别

如何使用缓存

有啥方法可以减少 Radius 异常值删除 [pcl 异常值删除] 的执行时间?

有啥办法可以刷新 JDialog 并重新制作它?

Javascript:有啥方法可以清除用户输入的历史记录?

有啥方法可以清除已经从安卓设备手动捕获的位置详细信息?