cache的用法.docx_第1页
cache的用法.docx_第2页
cache的用法.docx_第3页
cache的用法.docx_第4页
cache的用法.docx_第5页
已阅读5页,还剩22页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

细说 ASP.NET Cache 及其高级用法阅读目录 开始 Cache的基本用途 Cache的定义 Cache常见用法 Cache类的特点 缓存项的过期时间 缓存项的依赖关系 - 依赖其它缓存项 缓存项的依赖关系 - 文件依赖 缓存项的移除优先级 缓存项的移除通知 巧用缓存项的移除通知 实现【延迟操作】 巧用缓存项的移除通知 实现【自动加载配置文件】 文件监视技术的选择 各种缓存方案的共存许多做过程序性能优化的人,或者关注过程程序性能的人,应该都使用过各类缓存技术。 而我今天所说的Cache是专指ASP.NET的Cache,我们可以使用HttpRuntime.Cache访问到的那个Cache,而不是其它的缓存技术。以前我在【我心目中的A核心对象】这篇博客中简单地提过它,今天我打算为它写篇专题博客,专门来谈谈它,因为它实在是太重要了。在这篇博客中, 我不仅要介绍它的一些常见用法,还将介绍它的一些高级用法。 在上篇博客【在.net中读写config文件的各种方法】的结尾处,我给大家留了一个问题,今天,我将在这篇博客中给出一个我认为较为完美的答案。本文提到的【延迟操作】方法(如:延迟合并写入数据库)属于我的经验总结,希望大家能喜欢这个思路。回到顶部Cache的基本用途提到Cache,不得不说说它的主要功能:改善程序性能。ASP.NET是一种动态页面技术,用ASP.NET技术做出来的网页几乎都是动态的,所谓动态是指:页面的内容会随着不同的用户或者持续更新的数据, 而呈现出不同的显示结果。既然是动态的,那么这些动态的内容是从哪里来的呢?我想绝大多数网站都有自己的数据源, 程序通过访问数据源获取页面所需的数据,然后根据一些业务规则的计算处理,最后变成适合页面展示的内容。由于这种动态页面技术通常需要从数据源获取数据,并经过一些计算逻辑,最终变成一些HTML代码发给客户端显示。而这些计算过程显然也是有成本的。 这些处理成本最直接可表现为影响服务器的响应速度,尤其是当数据的处理过程变得复杂以及访问量变大时,会变得比较明显。 另一方面,有些数据并非时刻在发生变化,如果我们可以将一些变化不频繁的数据的最终计算结果(包括页面输出)缓存起来, 就可以非常明显地提升程序的性能,缓存的最常见且最重要的用途就体现在这个方面。 这也是为什么一说到性能优化时,一般都将缓存摆在第一位的原因。 我今天要说到的ASP.NET Cache也是可以实现这种缓存的一种技术。 不过,它还有其它的一些功能,有些是其它缓存技术所没有的。回到顶部Cache的定义在介绍Cache的用法前,我们先来看一下Cache的定义:(说明:我忽略了一些意义不大的成员)/ 实现用于 Web 应用程序的缓存。无法继承此类。public sealed class Cache : IEnumerable / 用于 Cache.Insert(.) 方法调用中的 absoluteExpiration 参数中以指示项从不过期。 public static readonly DateTime NoAbsoluteExpiration; / 用作 Cache.Insert(.) 或 Cache.Add(.) / 方法调用中的 slidingExpiration 参数,以禁用可调过期。 public static readonly TimeSpan NoSlidingExpiration; / 获取或设置指定键处的缓存项。 public object thisstring key get; set; / 将指定项添加到 System.Web.Caching.Cache 对象,该对象具有依赖项、过期和优先级策略 / 以及一个委托(可用于在从 Cache 移除插入项时通知应用程序)。 public object Add(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority priority, CacheItemRemovedCallback onRemoveCallback); / 从 System.Web.Caching.Cache 对象检索指定项。 / key: 要检索的缓存项的标识符。 / 返回结果: 检索到的缓存项,未找到该键时为 null。 public object Get(string key); public void Insert(string key, object value); public void Insert(string key, object value, CacheDependency dependencies); public void Insert(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration); / 摘要: / 向 System.Web.Caching.Cache 对象中插入对象,后者具有依赖项、过期和优先级策略 / 以及一个委托(可用于在从 Cache 移除插入项时通知应用程序)。 / / 参数: / key: / 用于引用该对象的缓存键。 / / value: / 要插入缓存中的对象。 / / dependencies: / 该项的文件依赖项或缓存键依赖项。当任何依赖项更改时,该对象即无效, / 并从缓存中移除。如果没有依赖项,则此参数包含 null。 / / absoluteExpiration: / 所插入对象将过期并被从缓存中移除的时间。 / 如果使用绝对过期,则 slidingExpiration 参数必须为 Cache.NoSlidingExpiration。 / / slidingExpiration: / 最后一次访问所插入对象时与该对象过期时之间的时间间隔。如果该值等效于 20 分钟, / 则对象在最后一次被访问 20 分钟之后将过期并被从缓存中移除。如果使用可调过期,则 / absoluteExpiration 参数必须为 System.Web.Caching.Cache.NoAbsoluteExpiration。 / / priority: / 该对象相对于缓存中存储的其他项的成本,由 System.Web.Caching.CacheItemPriority 枚举表示。 / 该值由缓存在退出对象时使用;具有较低成本的对象在具有较高成本的对象之前被从缓存移除。 / / onRemoveCallback: / 在从缓存中移除对象时将调用的委托(如果提供)。 / 当从缓存中删除应用程序的对象时,可使用它来通知应用程序。 / / 异常: / System.ArgumentException: / 为要添加到 Cache 中的项设置 absoluteExpiration 和 slidingExpiration 参数。 / / System.ArgumentNullException: / key 或 value 参数为 null。 / / System.ArgumentOutOfRangeException: / 将 slidingExpiration 参数设置为小于 TimeSpan.Zero 或大于一年的等效值。 public void Insert(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority priority, CacheItemRemovedCallback onRemoveCallback); / 从应用程序的 System.Web.Caching.Cache 对象移除指定项。 public object Remove(string key); / 将对象与依赖项策略、到期策略和优先级策略 / 以及可用来在从缓存中移除项【之前】通知应用程序的委托一起插入到 Cache 对象中。 / 注意:此方法受以下版本支持:3.5 SP1、3.0 SP1、2.0 SP1 public void Insert(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemUpdateCallback onUpdateCallback);ASP.NET为了方便我们访问Cache,在HttpRuntime类中加了一个静态属性Cache,这样,我们就可以在任意地方使用Cache的功能。 而且,ASP.NET还给它增加了二个“快捷方式”:Page.Cache, HttpContext.Cache,我们通过这二个对象也可以访问到HttpRuntime.Cache, 注意:这三者是在访问同一个对象。Page.Cache访问了HttpContext.Cache,而HttpContext.Cache又直接访问HttpRuntime.Cache回到顶部Cache常见用法通常,我们使用Cache时,一般只有二个操作:读,写。要从Cache中获取一个缓存项,我们可以调用Cache.Get(key)方法,要将一个对象放入缓存,我们可以调用Add, Insert方法。 然而,Add, Insert方法都有许多参数,有时我们或许只是想简单地放入缓存,一切接受默认值,那么还可以调用它的默认索引器, 我们来看一下这个索引器是如何工作的:public object thisstring key get return this.Get(key); set this.Insert(key, value); 可以看到:读缓存,其实是在调用Get方法,而写缓存则是在调用Insert方法的最简单的那个重载版本。注意了:Add方法也可以将一个对象放入缓存,这个方法有7个参数,而Insert也有一个签名类似的重载版本, 它们有着类似的功能:将指定项添加到 System.Web.Caching.Cache 对象,该对象具有依赖项、过期和优先级策略以及一个委托(可用于在从 Cache 移除插入项时通知应用程序)。然而,它们有一点小的区别:当要加入的缓存项已经在Cache中存在时,Insert将会覆盖原有的缓存项目,而Add则不会修改原有缓存项。也就是说:如果您希望某个缓存项目一旦放入缓存后,就不要再被修改,那么调用Add确实可以防止后来的修改操作。 而调用Insert方法,则永远会覆盖已存在项(哪怕以前是调用Add加入的)。从另一个角度看,Add的效果更像是 static readonly 的行为,而Insert的效果则像 static 的行为。注意:我只是说【像】,事实上它们比一般的static成员有着更灵活的用法。由于缓存项可以让我们随时访问,看起来确实有点static成员的味道,但它们有着更高级的特性,比如: 缓存过期(绝对过期,滑动过期),缓存依赖(依赖文件,依赖其它缓存项),移除优先级,缓存移除前后的通知等等。 后面我将会分别介绍这四大类特性。回到顶部Cache类的特点Cache类有一个很难得的优点,用MSDN上的说话就是:此类型是线程安全的。为什么这是个难得的优点呢?因为在.net中,绝大多数类在实现时,都只是保证静态类型的方法是线程安全, 而不考虑实例方法是线程安全。这也算是一条基本的.NET设计规范原则。对于那些类型,MSDN通常会用这样的话来描述:此类型的公共静态(在 Visual Basic 中为 Shared)成员是线程安全的。但不能保证任何实例成员是线程安全的。所以,这就意味着我们可以在任何地方读写Cache都不用担心Cache的数据在多线程环境下的数据同步问题。 多线程编程中,最复杂的问题就是数据的同步问题,而Cache已经为我们解决了这些问题。不过我要提醒您:ASP.NET本身就是一个多线程的编程模型,所有的请求是由线程池的线程来处理的。 通常,我们在多线程环境中为了解决数据同步问题,一般是采用锁来保证数据同步, 自然地,ASP.NET也不例外,它为了解决数据的同步问题,内部也是采用了锁。说到这里,或许有些人会想:既然只一个Cache的静态实例,那么这种锁会不会影响并发?答案是肯定的,有锁肯定会在一定程度上影响并发,这是没有办法的事情。然而,ASP.NET在实现Cache时,会根据CPU的个数创建多个缓存容器,尽量可能地减小冲突, 以下就是Cache创建的核心过程:internal static CacheInternal Create() CacheInternal internal2; int numSingleCaches = 0; if( numSingleCaches = 0 ) uint numProcessCPUs = (uint)SystemInfo.GetNumProcessCPUs(); numSingleCaches = 1; for( numProcessCPUs -= 1; numProcessCPUs 0; numProcessCPUs = numProcessCPUs 1 ) numSingleCaches = numSingleCaches 1; CacheCommon cacheCommon = new CacheCommon(); if( numSingleCaches = 1 ) internal2 = new CacheSingle(cacheCommon, null, 0); else internal2 = new CacheMultiple(cacheCommon, numSingleCaches); cacheCommon.SetCacheInternal(internal2); cacheCommon.ResetFromConfigSettings(); return internal2;说明:CacheInternal是个内部用的包装类,Cache的许多操作都要由它来完成。在上面的代码中,numSingleCaches的计算过程很重要,如果上面代码不容易理解,那么请看我下面的示例代码:static void Main() for( uint i = 1; i 0; numProcessCPUs = numProcessCPUs 1 ) numSingleCaches = numSingleCaches 1; Console.Write(numSingleCaches + ,);程序将会输出:1,2,4,4,8,8,8,8,16,16,16,16,16,16,16,16,32,32,32,32CacheMultiple的构造函数如下:internal CacheMultiple(CacheCommon cacheCommon, int numSingleCaches) : base(cacheCommon) this._cacheIndexMask = numSingleCaches - 1; this._caches = new CacheSinglenumSingleCaches; for (int i = 0; i numSingleCaches; i+) this._cachesi = new CacheSingle(cacheCommon, this, i); 现在您应该明白了吧:CacheSingle其实是ASP.NET内部使用的缓存容器,多个CPU时,它会创建多个缓存容器。在写入时,它是如何定位这些容器的呢?请继续看代码:internal CacheSingle GetCacheSingle(int hashCode) hashCode = Math.Abs(hashCode); int index = hashCode & this._cacheIndexMask; return this._cachesindex;说明:参数中的hashCode是直接调用我们传的key.GetHashCode() ,GetHashCode是由Object类定义的。所以,从这个角度看,虽然ASP.NET的Cache只有一个HttpRuntime.Cache静态成员,但它的内部却可能会包含多个缓存容器, 这种设计可以在一定程度上减少并发的影响。不管如何设计,在多线程环境下,共用一个容器,冲突是免不了的。如果您只是希望简单的缓存一些数据, 不需要Cache的许多高级特性,那么,可以考虑不用Cache 。 比如:可以创建一个Dictionary或者Hashtable的静态实例,它也可以完成一些基本的缓存工作, 不过,我要提醒您:您要自己处理多线程访问数据时的数据同步问题。顺便说一句:Hashtable.Synchronized(new Hashtable()也是一个线程安全的集合,如果想简单点,可以考虑它。接下来,我们来看一下Cache的高级特性,这些都是Dictionary或者Hashtable不能完成的。回到顶部缓存项的过期时间ASP.NET支持二种缓存项的过期策略:绝对过期和滑动过期。1. 绝对过期,这个容易理解:就是在缓存放入Cache时,指定一个具体的时间。当时间到达指定的时间的时,缓存项自动从Cache中移除。2. 滑动过期:某些缓存项,我们可能只希望在有用户在访问时,就尽量保留在缓存中,只有当一段时间内用户不再访问该缓存项时,才移除它, 这样可以优化内存的使用,因为这种策略可以保证缓存的内容都是【很热门】的。 操作系统的内存以及磁盘的缓存不都是这样设计的吗?而这一非常有用的特性,Cache也为我们准备好了,只要在将缓存项放入缓存时, 指定一个滑动过期时间就可以实现了。以上二个选项分别对应Add, Insert方法中的DateTime absoluteExpiration, TimeSpan slidingExpiration这二个参数。注意:这二个参数都是成对使用的,但不能同时指定它们为一个【有效】值,最多只能一个参数值有效。 当不使用另一个参数项时,请用Cache类定义二个static readonly字段赋值。这二个参数比较简单,我就不多说了,只说一句:如果都使用Noxxxxx这二个选项,那么缓存项就一直保存在缓存中。(或许也会被移除)回到顶部缓存项的依赖关系 - 依赖其它缓存项ASP.NET Cache有个很强大的功能,那就是缓存依赖。一个缓存项可以依赖于另一个缓存项。 以下示例代码创建了二个缓存项,且它们间有依赖关系。首先请看页面代码: Key1 的缓存内容: 页面后台代码:public partial class CacheDependencyDemo : System.Web.UI.Page SubmitMethod(AutoRedirect=true) private void SetKey1Cache() SetKey2Cache(); CacheDependency dep = new CacheDependency(null, new string key2 ); HttpRuntime.Cache.Insert(key1, DateTime.Now.ToString(), dep, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration); SubmitMethod(AutoRedirect=true) private void SetKey2Cache() HttpRuntime.Cache.Insert(key2, Guid.NewGuid().ToString(); 当运行这个示例页面时,运行结果如下图所示, 点击按钮【设置Key1的值】时,将会出现缓存项的内容(左图)。点击按钮【设置Key2的值】时,此时将获取不到缓存项的内容(右图)。根据结果并分析代码,我们可以看出,在创建Key1的缓存项时,我们使用了这种缓存依赖关系:CacheDependency dep = new CacheDependency(null, new string key2 );所以,当我们更新Key2的缓存项时,Key1的缓存就失效了(不存在)。不要小看了这个示例。的确,仅看这几行示例代码,或许它们实在是没有什么意义。 那么,我就举个实际的使用场景来说明它的使用价值。上面这幅图是我写的一个小工具。在示意图中,左下角是一个缓存表CacheTable,它由一个叫Table1BLL的类来维护。 CacheTable的数据来源于Table1,由Table1.aspx页面显示出来。 同时,ReportA, ReportB的数据也主要来源于Table1,由于Table1的访问几乎绝大多数都是读多写少,所以,我将Table1的数据缓存起来了。 而且,ReportA, ReportB这二个报表采用GDI直接画出(由报表模块生成,可认是Table1BLL的上层类),鉴于这二个报表的浏览次数较多且数据源是读多写少, 因此,这二个报表的输出结果,我也将它们缓存起来。在这个场景中,我们可以想像一下:如果希望在Table1的数据发生修改后,如何让二个报表的缓存结果失效?让Table1BLL去通知那二个报表模块,还是Table1BLL去直接删除二个报表的缓存?其实,不管是选择前者还是后者,当以后还需要在Table1的CacheTable上做其它的缓存实现时(可能是其它的新报表), 那么,势必都要修改Table1BLL,那绝对是个失败的设计。 这也算是模块间耦合的所带来的恶果。幸好,ASP.NET Cache支持一种叫做缓存依赖的特性,我们只需要让Table1BLL公开它缓存CacheTable的KEY就可以了(假设KEY为 CacheTableKey), 然后,其它的缓存结果如果要基于CacheTable,设置一下对【CacheTableKey】的依赖就可以实现这样的效果:当CacheTable更新后,被依赖的缓存结果将会自动清除。这样就彻底地解决了模块间的缓存数据依赖问题。回到顶部缓存项的依赖关系 - 文件依赖在上篇博客【在.net中读写config文件的各种方法】的结尾, 我给大家留了一个问题:我希望在用户修改了配置文件后,程序能立刻以最新的参数运行,而且不用重启网站。今天我就来回答这个问题,并给出所需的全部实现代码。首先,我要说明一点:上次博客的问题,虽然解决方案与Cache的文件依赖有关,但还需与缓存的移除通知配合使用才能完美的解决问题。 为了便于内容的安排,我先使用Cache的文件依赖来简单的实现一个粗糙的版本,在本文的后续部分再来完善这个实现。先来看个粗糙的版本。假如我的网站中有这样一个配置参数类型:/ / 模拟网站所需的运行参数/ public class RunOptions public string WebSiteUrl; public string UserName;我可以将它配置在这样一个XML文件中: /fish-li fish li再来一个用于显示运行参数的页面: WebSiteUrl: UserName: 下面的代码就可以实现:在XML修改后,浏览页面就能立即看到最新的参数值:public static class WebSiteApp private static readonly string RunOptionsCacheKey = Guid.NewGuid().ToString(); public static RunOptions RunOptions get / 首先尝试从缓存中获取运行参数 RunOptions options = HttpRuntime.CacheRunOptionsCacheKey as RunOptions; if( options = null ) / 缓存中没有,则从文件中加载 string path = HttpContext.Current.Server.MapPath(/App_Data/RunOptions.xml); options = RwConfigDemo.XmlHelper.XmlDeserializeFromFile(path, Encoding.UTF8); / 把从文件中读到的结果放入缓存,并设置与文件的依赖关系。 CacheDependency dep = new CacheDependency(path); / 如果您的参数较复杂,与多个文件相关,那么也可以使用下面的方式,传递多个文件路径。 /CacheDependency dep = new CacheDependency(new string path ); HttpRuntime.Cache.Insert(RunOptionsCacheKey, options, dep); return options; 注意:这里仍然是在使用CacheDependency,只是我们现在是给它的构造函数的第一个参数传递要依赖的文件名。在即将结束对缓存的依赖介绍之前,还要补充二点:1. CacheDependency还支持【嵌套】,即:CacheDependency的构造函数中支持传入其它的CacheDependency实例,这样可以构成一种非常复杂的树状依赖关系。2. 缓存依赖的对象还可以是SQL SERVER,具体可参考SqlCacheDependency回到顶部缓存项的移除优先级缓存的做法有很多种,一个静态变量也可以称为是一个缓存。一个静态的集合就是一个缓存的容器了。 我想很多人都用Dictionary,List,或者Hashtable做过缓存容器,我们可以使用它们来保存各种数据,改善程序的性能。 一般情况下,如果我们直接使用这类集合去缓存各类数据,那么,那些数据所占用的内存将不会被回收,哪怕它们的使用机会并不是很多。 当缓存数据越来越多时,它们所消耗的内存自然也会越来越多。那么,能不能在内存不充足时,释放掉一些访问不频繁的缓存项呢?这个问题也确实是个较现实的问题。虽然,使用缓存会使用程序运行更快,但是,我们数据会无限大,不可能统统缓存起来, 毕竟,内存空间是有限的。因此,我们可以使用前面所说的基于一段时间内不再访问就删除的策略来解决这个问题。 然而,在我们编码时,根本不知道我们的程序会运行在什么配置标准的计算机上,因此,根本不可能会对内存的大小作出任何假设, 此时,我们可能会希望当缓存占用过多的内存时,且当内存不够时,能自动移除一些不太重要的缓存项,这或许也比较有意义。对于这个需求,在.net framework提供了二种解决办法,一种是使用WeakReference类,另一种是使用Cache 。 不过,既然我们是在使用ASP.NET,选择Cache当然会更方便。 在Cache的Add, Insert方法的某些重载版本中,可以指定缓存项的保存优先级策略,由参数CacheItemPriority priority来传入。 其中,CacheItemPriority是一个枚举类型,它包含了如下枚举值:/ 指定 Cache 对象中存储的项的相对优先级。public enum CacheItemPriority / 在服务器释放系统内存时,具有该优先级级别的缓存项最有可能被从缓存删除。 Low = 1, / 在服务器释放系统内存时,具有该优先级级别的缓存项比分配了 CacheItemPriority.Normal / 优先级的项更有可能被从缓存删除。 BelowNormal = 2, / 在服务器释放系统内存时,具有该优先级级别的缓存项很有可能被从缓存删除, / 其被删除的可能性仅次于具有 CacheItemPriority.Low / 或 CacheItemPriority.BelowNormal 优先级的那些项。这是默认选项。 Normal = 3, / 缓存项优先级的默认值为 CacheItemPriority.Normal。 Default = 3, / 在服务器释放系统内存时,具有该优先级级别的缓存项被删除的可能性 / 比分配了 CacheItemPriority.Normal 优先级的项要小。 AboveNormal = 4, / 在服务器释放系统内存时,具有该优先级级别的缓存项最不可能被从缓存删除。 High = 5, / 在服务器释放系统内存时,具有该优先级级别的缓存项将不会被自动从缓存删除。 / 但是,具有该优先级级别的项会根据项的绝对到期时间或可调整到期时间与其他项一起被移除。 NotRemovable = 6,说明:当我们调用Cache的Add, Insert方法时,如果不指定CacheItemPriority选项,最终使用Normal所代表的优先级。 如果我们希望将某个可能不太重要的数据放入缓存时,可以指定优先级为Low或者BelowNormal。 如果想让缓存项在内存不足时,也不会被移除(除非到期或者依赖项有改变),可使用NotRemovable。显然,我们可以使用这个特性来控制缓存对内存压力的影响。 其它的缓存方案,如static Collection + WeakReference也较难实现这样灵活的控制。回到顶部缓存项的移除通知ASP.NET Cache与一些static变量所实现的缓存效果并不相同,它的缓存项是可以根据一些特定的条件失效的,那些失效的缓存将会从内存中移除。 虽然,某些移除条件并不是由我们的代码直接解发的,但ASP.NET还是提供一种方法让我们可以在缓存项在移除时,能通知我们的代码。注意哦:ASP.NET Cache支持移除【前】通知 和 移除【后】通知二种通知方式。我们可以在调用Add, Insert方法时,通过参数onRemoveCallback传递一个CacheItemRemovedCallback类型的委托,以便在移除指定的缓存项时, 能够通知我们。这个委托的定义如下:/ / 定义在从 System.Web.Caching.Cache 移除缓存项时通知应用程序的回调方法。/ / 从缓存中移除的键(当初由Add, Insert传入的)。/ 与从缓存中移除的键关联的缓存项(当初由Add, Insert传入的)。/ 从缓存移除项的原因。 public delegate void CacheItemRemovedCallback(string key, object value, CacheItemRemovedReason reason);/ 指定从 System.Web.Caching.Cache 对象移除项的原因。public enum CacheItemRemovedReason / 该项是通过指定相同键的 Cache.Insert(System.String,System.Object) / 方法调用或 Cache.Remove(System.String) 方法调用从缓存中移除的。 Removed = 1, / 从缓存移除该项的原因是它已过期。 Expired = 2, / 之所以从缓存中移除该项,是因为系统要通过移除该项来释放内存。 Underused = 3, / 从缓存移除该项的原因是与之关联的缓存依赖项已更改。 DependencyChanged = 4,委托的各个参数的含义以及移除原因,在注释中都有明确的解释,我也不再重复了。我想:有很多人知道Cache的Add, Insert方法有这个参数,也知道有这个委托,但是,它们有什么用呢? 在后面的二个小节中,我将提供二个示例来演示这一强大的功能。通常,我们会以下面这种方式从Cache中获取结果:RunOptions options = HttpRuntime.CacheRunOptionsCacheKey as RunOptions;if( options = null ) / 缓存中没有,则从文件中加载 / . HttpRuntime.Cache.Insert(RunOptionsCacheKey, options, dep);return options;这其实也是一个惯用法了:先尝试从缓存中获取,如果没有,则从数据源中加载,并再次放入缓存。为什么会在访问Cache时返回null呢?答案无非就是二种原因:1. 根本没有放入Cache,2. 缓存项失效被移除了。这种写法本身是没有问题,可是,如果从数据源中加载数据的时间较长,情况会怎样呢?显然,会影响后面第一次的访问请求。您有没有想过,如果缓存项能一直放在Cache中,那不就可以了嘛。 是的,通常来说,只要您在将一个对象放入Cache时,不指定过期时间,不指定缓存依赖,且设置为永不移除,那么对象确实会一直在Cache中, 可是,过期时间和缓存依赖也很有用哦。如何能二者兼得呢?为了解决这个问题,微软在.net framework的3.5 SP1、3.0 SP1、2.0 SP1版本中,加入了【移除前通知】功能,不过,这个方法仅受Insert支持, 随之而来的还有一个委托和一个移除原因的枚举定义:/ / 定义一个回调方法,用于在从缓存中移除缓存项之前通知应用程序。/ / 要从缓存中移除的项的标识符。/ 要从缓存中移除项的原因。/ 此方法返回时,包含含有更新的缓存项对象。/ 此方法返回时,包含新的依赖项的对象。/ 此方法返回时,包含对象的到期时间。/ 此方法返回时,包含对象的上次访问时间和对象的到期时间之间的时间间隔。public delegate void CacheItemUpdateCallback(string key, CacheItemUpdateReason reason, out object expensiveObject, out CacheDependency dependency, out DateTime absoluteExpiration, out TimeSpan slidingExpiration);/ / 指定要从 Cache 对象中移除缓存项的原因。/ public enum CacheItemUpdateReason / / 指定要从缓存中移除项的原因是绝对到期或可调到期时间间隔已到期。 / Expired = 1, / / 指定要从缓存中移除项的原因是关联的 CacheDependency

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论