简介
这是一个缓存序列化的对象一般框架。它具有高速缓存内存/磁盘缓存任何对象的泛型类。如果没有更多的内存,它是从磁盘读取。
它也有一个不相同的CacheDictionary,但有一些小的数据的优化,避免了许多quot;缓冲filesquot;产生。
,最后,所有的最好:在您的项目添加App_Browsers,你可以使所有viewstates使用这种技术,所以只有一个小ViewId完整的视图状态,而不是发送到客户端。此外,一段时间后,它会删除未使用的文件和reutilizes完全相同的文件,避免浪费硬盘空间。背景
我没有真正面对很多问题时,与Web工作。我开始程序时,计算机只有1MB或2MB。但是,我看到,在一般人是位时存储数据丢失了。 ViewState和会议上的文件也混乱,他们看起来互换,当他们不。
我首先创建一个分页记录集缓存技术。
然后,我创建的任何数据缓存技术。
和,最后,模块做的ViewStates。实在是伟大的,工作了一年多没有问题。它如何工作(基本)
执行可以是非常复杂的,因为代码是线程安全的,您需要妥善管理垃圾收集,但原理很简单:每个对象quot; bufferquot;被序列化并创建一个缓冲的hashCode(校验)。如果该缓冲区的目录存在,我看看是否有一些具有相同长度的缓冲区,如果有,如果是相同的,从而避免创建一个新的,我创建了一个新的唯一ID,保存该文件,并返回该缓冲区的ID和hashCode。这之间的所有会话共享,但数据是只读,是没有问题的。第1项是BufferId,不ViewId。现在,随着bufferId,我试图找到如果在内存中的实际会议包含bufferId的ViewState信息。如果没有包含,产生一个新的ViewId。如果存在,旧的ID返回。很显然,每一次我重新利用一个文件,我做了一个保持活动(文件,更新文件的日期/时间,并在内存中,调用GCUtils.KeepAlive)。每个缓冲区也保持在内存中的弱引用,但要避免最近收集的缓冲区,我呼吁GCUtils.KeepAlive。 GCUtils.KeepAlive(不GC.KeepAlive)担保对象将生存下一次收集。ViewIds创建的SessionID,所以有没有一个其他的ViewState的用户问题,即使内部缓冲区是相同的(在这种情况下,,每个用户都会有不同的的ViewIds,但他们会指向同一个缓冲区)。此外,每个页面生成一个新的的视图状态,因此,我想如果可能的话现有的视图状态的ID,我创建一个新的文件。默认情况下,FileCachePersister运行在30分钟的过程中,4个多小时中删除文件。这已无关会话过期时间。Hownbsp,它的工作原理(高级)
在这个时刻,我不会解释CacheDictionary的细节(这是一个有效的缓存对象的字典,但与一些优化),也不能解释WeakDictionary,因为其解释本身将大于整篇文章。但重要的是要知道,这是一本字典,允许其项目由垃圾收集器收集,但保持其最近使用的值活着。
我会开始解释CacheManager的。 CacheManager的类负责加载和保存的缓冲区(字节),因为它不知道任何对象的真实类型。最重要的是,它已经是一个WeakDictionary键缓冲区的哈希码,和值字典的ID和序列化的字节。其内部职能试图找到内存使用hashCode和缓冲区的ID值,如果没有被发现,没有要求的持续程序加载它,然后将其存储在这些弱字典装载值(如有),做一个他们的KeepAlive上。保存功能做了类似的过程,试图找到在内存兼容的缓冲区,重新利用的ID,如果没有找到,呼叫持续程序保存并返回生成的ID。
缓存泛型类是序列化和反序列化缓冲器的能力之一。它使用CacheManager的读取或写入这些缓冲区,但高速缓存本身有其自己的WeakReference为有效的对象。这样做是因为,在反序列化缓存对象时,唯一的对象ID是必要的,不是真正的对象。如果太多quot; identicalquot;对象被放置在高速缓存中中,所有的缓存对象可以有效对象收集,但也许缓冲区再生他们仍然在内存中。可以看多余的,但在我的经验,事实并非如此。
,所以,你创建一个对象缓存。缓存序列化的对象,并调用CacheManager的,这将尝试重新利用一些相同的缓冲区的ID,或将要求它要保存...但是,在那里将它保存?
的持续程序的工作。的框架内,只持续程序存在,并且已经可用了FileCachePersister。它简单的接收参数和尝试加载该文件,如果存在,则返回null。它接收的文件名,并尝试更新日期/时间,以保持它活着,或保存文件。这是在这样一种方式,使thatnbsp,您可以轻松地创建一个持续程序存储到数据库中的数据,或使用远程服务器,也可以有自己的缓存,避免并发进程在同一时间访问相同的文件。这很重要,FileCachePersister工程非常好,许多线程,但只有一个进程,必须使用目录。
OK,在FileCachePersister有一个线程来删除旧文件,但没有什么复杂。在ViewState
ViewState的解决方案是非常相似的缓存解决方案,但它也有额外的安全信息。这个类负责装载和保存ViewStates的是PfzPageStatePersister。 CacheManager的类,它有一本字典的SessionIds组成,所以ViewIds是独家的实际会话,然后值ViewIds字典,该字典的价值观产生的ViewState的页面(这样的类型的ViewId复制到另一个页面不能正常工作)和有效的ViewState信息。
或更好,一个这样的值的缓存。为什么呢?因为如果你从一个网页到另一个,产生相同的viewstates,只有将产生一个新的"; referencequot缓冲区,但缓冲区,这可能会非常大,是相同的。它看起来有点复杂,因为它有一对,但因为的方式PageStatesPersisters一般的作品,因为他们只产生两个对象,它唯一的目的,被序列化。说实话不是很友好。
但是,然后,这个想法是相同的:
看,如果在内存中的ViewState。如果不是,请为持续程序来加载它。
保存的时候,在内存中搜索一个相同的ViewState,或创建一个新的,调用保存它的持续程序。使用代码
CacheManager的类,在这一切都始于。而且,如果你使用框架只保存在文件中viewstates,它结束。在Global.asax中,把以下(或类似):
其他有趣的东西 CacheManager.Persister = new FileCachePersister
("c:\\temp\\PfzCachingWebApplication_ViewStates\\");
CacheManager.Start();
GCUtils - 我已经提出在另一篇文章中这一类,但它现在修改。登记收集的事件,您可以获悉最近发生的集合,如果您有任何额外的内存,你可以免费(如调用TrimExcess)。 GCUtils.KeepAlive是非常有用的,作为一种方式来告诉GarbageCollector以避免收集最近使用的对象,即使他们只具有弱引用。
Cache类的使用 - 您可以使用Cache类,即使在Windows窗体或如果你真的需要把一些在Session中的大量信息,而不是把它的ViewState。
例如,当你把会话中的对象时,您创建的缓存对象,并在会议缓存对象:{C}
,读它,你这样做: byte[] data = ((Cache<byte[]>)Session["MyVeryLargeItem"]).Target;
在正常的代码,你将仍然需要转换,但一般不创建缓存,不投回来到高速缓存,然后读取目标。但是,这个额外的步骤将使您的5MB对象成为类似会议32字节,而5MB保存在文件中。对同一主题的未来文章
在以后的文章中,我打算解释很好的例子使用Cache类,CacheDictionary,WeakDictionary和特别StatedPage。但是,这些都是我个人的框架的一部分,而不是真正的ViewState的解决方案的一部分,因为他们独立工作的ViewState,甚至可以在非web应用中使用。
在这篇文章中,我只是想显示的ViewState的解决方案,真正起作用(在生产现在是很长一段时间),不改变编程方式,除了事实的,现在你可以分页记录存储在ViewState中的数据集,因为它不会被发送到客户端。历史2009年10月7日:战后初期