基本上我正在处理一个处理大量视频和图像文件的程序,而我正在努力处理它的内存管理方面因为我以前从未处理过这样的事情。
例如,它将所有这些图像存储在数据库中,并加载视频列表,然后您可以在视频之间切换并查看视频中的图像。现在,它一直将所有这些图像保存在内存中,这占用了大量空间。我知道我可以懒得加载图像,但是一旦你来回切换,你就会把它们全部卡在内存中。
我想尽可能利用WPF数据绑定功能和MVVM,但如果我需要查看不同的架构,我会。
我只是在寻找一般性建议,提示,文章链接或任何有用的建议。
答案 0 :(得分:3)
您可以看到的一件事是数据虚拟化,默认情况下WPF中没有提供它(它们提供了UI虚拟化)。数据虚拟化可以说“在可见时加载和绑定项目/项目范围的数据,然后在不可见时卸载”。
这是一篇很棒的文章,描述了您可以按原样使用或改编的具体实现:
http://www.codeproject.com/KB/WPF/WpfDataVirtualization.aspx
答案 1 :(得分:3)
听起来你遇到的主要问题不是应用程序的性能密集程度(固定大小的缓冲区和静态分配会有所帮助),而是整体内存占用。控制的方法是使用虚拟化。
延迟加载让你到达那里:在实际需要之前,你实际上并没有创建对象。这没关系,但用户使用应用程序的时间越长,他在UI中访问的对象越多,创建的对象就越多,最终应用程序内存不足。
所以你想扔掉用户不再需要的对象。确定用户不需要哪些对象可能是一个难题,但它也可以像假设用户不需要他最近最少使用的对象一样容易。您使用最近最少使用(LRU)缓存来执行此操作。
这与MVVM模式完全一致。在您的视图类中,您使对象的属性getter使用此伪代码:
if object hasn't been loaded
load object
add object to the LRU cache (whether you loaded it or not)
return object
The LRU cache I wrote保留其包含的对象的简单队列。将对象添加到缓存时,如果它尚未在队列中,则会将其添加到后面,如果它已经在队列中,则会将其移动到后面。
如果队列在添加对象时达到其容量,则会弹出队列前端的任何内容(最近最少使用的队列)并引发DiscardingOldestItem
事件。
此事件是对象有机会告诉任何持有它的引用(即它是属性的视图对象)需要丢弃它(可能通过引发它自己的事件)。视图对象的事件处理程序应首先引发PropertyChanged
事件。如果属性getter在执行此操作时被调用,那么在某处仍然会查看属性的绑定,因此它不应该被丢弃。 (此外,由于调用了getter,对象才被移动到队列的后面。)否则,它可以被丢弃。
(请注意,如果你在UI中看到的对象多于缓存可以容纳的对象,那么这个小舞会变成一个无限循环,你会得到一个堆栈溢出。)
更复杂的方法是,当应用程序开始运行内存不足时,LRU缓存会开始丢弃旧项目(它现在使用固定容量)。这是一个直接的改变,但是如果你做了那个改变,前一段中描述的场景是你需要更多考虑的事情;一个非常大的对象可能会导致整个用户界面发生变化。
答案 2 :(得分:1)
似乎为了提高原始性能,您实际上希望避免使用模式。它们有它们的用途,不要误会我的意思,但是如果你试图以最高性能爆炸视频,你需要做的最后一件事就是引入抽象层,这些抽象层旨在编写更高质量的代码,而不是提高应用程序性能
答案 3 :(得分:1)
this article有很多关于这个主题的好信息,尽管它更多是c和c ++。
静态分配模式:预先分配内存
它暗示, 池分配模式:预分配所需对象池
固定大小的缓冲区模式:以相同大小的块分配内存
智能指针模式:使指针可靠
垃圾收集模式:自动回收丢失的内存
Garbage Compactor Pattern:自动碎片整理并回收内存
答案 4 :(得分:0)
“我知道我可以懒得加载图片, 但是一旦你换回来了 你会把所有人都陷入其中 存储器“。
这不符合我的理解。通过删除所有引用,图像可以像其他任何东西一样收集垃圾。你确定你在某个地方没有引用它们吗?尝试使用memprofiler或ANTS等内存分析器来查看发生的情况。
对于那些发现这个问题寻找一般模式(不是WPF)来减少记忆的人,那个着名的(我从未见过用过的!)是The Flyweight pattern