当前位置: 首页 > 编程语言 > C#

C#的对象缓存分享

时间:2023-04-10 19:02:18 C#

C#的对象缓存我正在为一些文档格式开发文档查看器。为方便起见,我们假设这是一个PDF查看器,一个桌面应用程序。该软件的一项要求是渲染速度。所以,现在,当用户滚动文档时,我正在缓存下一页的图像。这行得通,UI非常灵敏,应用程序似乎几乎立即呈现页面......但代价是:内存使用有时会达到600MB。我把它全部缓存在内存中。现在,我知道,我可以缓存到磁盘,但一直这样做会明显变慢。我想做的是实现一些缓存(LRU?),其中一些缓存页面(图像对象)在内存中,大部分在磁盘上。在我开始之前,框架或库中是否有可以为我做这件事的东西?这似乎是一个非常普遍的问题。(这是一个桌面应用程序,不是ASP.NET)或者,您对这个问题还有其他想法吗?我写了一个LRUCache和一些测试用例,大家可以放心使用。您可以在我的博客上阅读源代码。对懒惰(这里是减少测试用例):usingSystem;使用System.Collections.Generic;使用System.Linq;使用系统文本;命名空间LRUCache{公共类IndexedLinkedList{LinkedList数据=newLinkedList();字典>索引=新字典>();publicvoidAdd(Tvalue){index[value]=data.AddLast(value);}publicvoidRemoveFirst(){index.Remove(data.First.Value);数据.RemoveFirst();}publicvoidRemove(Tvalue){LinkedListNode节点;if(index.TryGetValue(value,outnode)){data.Remove(node);index.Remove(值);}}publicintCount{get{返回数据。}}publicvoidClear(){data.Clear();index.Clear();}publicTFirst{get{returndata.First.Value;}}}}LRUCache使用系统;使用System.Collections.Generic;使用System.Linq;使用系统文本;namespaceLRUCache{publicclassLRUCache:IDictionary{objectsync=newobject();词典数据;IndexedLinkedListlruList=newIndexedLinkedList();ICollection>dataAsCollection;内部容量;publicLRUCache(intcapacity){if(capacity(capacity);dataAsCollection=data;this.capacity=capacity;}publicvoidAdd(TKeykey,TValuevalue){if(!ContainsKey(key)){this[key]=value;}else{thrownewArgumentException("试图在缓存中插入重复键。");}}publicboolContainsKey(TKeykey){returndata.ContainsKey(key);}publicICollectionKeys{get{returndata.Keys;}}publicboolRemove(TKeykey){boolexisted=data.Remove(key);lruList.Remove(key);returnexisted;}publicboolTryGetValue(TKeykey,outTValuevalue){返回data.TryGetValue(key,outvalue);}publicICollectionValues{get{returndata.Values;}}publicTValuethis[TKeykey]{get{varvalue=data[key];lruList.Remove(key);lruList复制代码.Add(key);返回值;}set{data[key]=value;lruList.Remove(key);lruList.Add(key);if(data.Count>capacity){data.Remove(lruList.First);lruList.RemoveFirst();}}}publicvoidAdd(KeyValuePairitem){添加(item.Key,item.Value);}publicvoidClear(){data.Clear();lruList.Clear();}publicboolContains(KeyValuePairitem){返回dataAsCollection。包含(项目);}publicvoidCopyTo(KeyValuePair[]array,intarrayIndex){dataAsCollection.CopyTo(array,arrayIndex);}publicintCount{get{返回数据。}}publicboolIsReadOnly{get{returnfalse;}}publicboolRemove(KeyValuePairitem){boolremoved=dataAsCollection.Remove(item);如果(删除){lruList.Remove(item.Key);返回删除;}publicIEnumerator>GetEnumerator(){返回dataAsCollection。获取枚举器();}System.Collections.IEnumeratorSystem.Collections.IEnumerable.GetEnumerator(){返回((System.Collections.IEnumerable)data).GetEnumerator();}}}对于.NET4.0,您还可以使用System.MemoryCacheforRuntime.Cachinghttp://msdn.microsoft.com/en-us/library/system.runtime.caching.aspx有企业库的模式和实践(更具体地说,缓存应用程序块),但IMO往往是矫枉过正设计过于复杂。.NETFramework始终能够维护对对象的弱引用。基本上,弱引用是对运行时认为“不重要”的对象的引用,并且可以在垃圾收集运行时随时删除。例如,这可用于缓存内容,但您无法控制收集什么和不收集什么。另一方面,它使用起来非常简单,可能正是您所需要的。Dave经典权衡情况。将所有内容保存在内存中是以内存消耗大量增加为代价的,而从磁盘中检索可以减少内存消耗,但效果不是很好。但是,你已经知道这一切了!内置的System.Web.Caching.Cache类很棒,我自己在ASP.NET应用程序中多次使用它(虽然主要用于数据库记录缓存)但是,缺点是缓存只能在一台计算机上工作(通常是唯一的Web服务器),并且不能分布在多台计算机上。如果有可能“抛出一些硬件”问题,而且不一定需要昂贵的硬件,只需要有大量内存的盒子,你总是可以使用分布式缓存解决方案。这将为您提供更多内存,同时保持(几乎)相同的性能水平。.NET的分布式缓存解决方案的一些选项是:Memcached.NETindeXus.Net甚至是Microsoft自己的Velocity项目。你是如何实现缓存的?您可以使用System.Web.Caching的Cache类,即使是在非Web应用程序中,如果需要内存,它会以LRU为基础清除项目。在非Web应用程序中,您需要使用HttpRuntime.Cache来访问Cache实例。请注意,文档声明Cache类不打算在ASP.NET之外使用,尽管它一直对我有用。(但我从来没有在任何关键任务应用程序中依赖它。)但是,缓存应用程序块和ASP.NET缓存都是选项,虽然它们执行LRU,但唯一发生的磁盘利用率是内存分页。我认为有一些方法可以优化这些更具体的目标以获得更好的输出。这里有一些想法:我当然会避免使用普通哈希表。除了rsbarro关于使用MemoryCache的回答外,我还推荐使用PostSharpAOP,如http://www.codeproject.com/Articles/493971/Leveraging-MemoryCache-and-AOP-for-expensive-calls中所述有一个高效的An开源RAM虚拟器,它使用MRU算法将最近引用的对象保存在内存中,并使用快速、轻量级的后备存储(在磁盘上)“分页”它们。这是代码项目中关于它的迷你文章的链接:http://www.codeproject.com/Tips/827339/Virtual-Cache希望它有所帮助。以上就是C#学习教程:C#对象缓存分享的全部内容。如果对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右边联系管理员删除。如需转载请注明出处: