2009-08-26 435 views
6

我想弄清楚如何释放一个WriteableBitmap内存。WPF WriteableBitmap内存泄漏?

在代码的下一节我填一个WriteableBitmap的的后备缓冲有一个真正的大量“BigImage”(3600 * 4800像素,只是为了测试) 数据。如果我的评论,其中位图和图像都等于行为空,内存不会释放,应用程序消耗〜230 MB,甚至当图像和位图不再使用时,则会消耗 !

正如你可以在代码结束时看到它需要调用GC.Collect()来释放内存。

所以问题是,什么是正确的方式来释放WriteableBitmap对象使用的内存? GC.Collect()是唯一的方法吗?

任何帮助将是伟大的。

PS。对不起,我的英语不好。

private void buttonTest_Click(object sender, RoutedEventArgs e) 
{ 
      Image image = new Image(); 
      image.Source = new BitmapImage(new Uri("BigImage")); 

      WriteableBitmap bitmap = new WriteableBitmap(
       (BitmapSource)image.Source); 

      bitmap.Lock(); 

      // Bitmap processing 

      bitmap.Unlock(); 

      image = null; 
      bitmap = null; 

      GC.Collect(); 
} 
+0

http://stackoverflow.com/questions/1534983/how-to-dispose-a-writeable-bitmap-wpf/2422496#2422496 – nyxtom 2010-03-12 11:29:06

回答

0

强制GC没有设置imagebitmapnull,因为他们仍然被本地引用,因此被认为根引用不会清除它们。这与WriteableBitmap没什么关系,更多的是GC如何工作的问题。

如果您没有将它们设置为null并且不强制进行垃圾回收,那么只要方法存在并发生GC,就会收集它们。以上建议您自己强制收集,因为您可能会伤害到性能而不是帮助它。

+0

谢谢两位的帮助。 问题是垃圾收集器似乎没有收集图像和位图使用的内存。如果我将它们分配的行注释为null,并且一旦该方法完成执行,整个应用程序使用的内存将保持大约234 MB。 看起来像一个非常麻烦的行为。 再次感谢您。 – Mario 2009-08-26 14:14:07

+0

保持多久?你确定垃圾收集器实际上是在收集吗?打开perfmon并观察GC计数器,看它是否真的在收集。如果没有,你没有什么可担心的 - 没有内存压力,所以GC不是必需的。 – 2009-08-26 15:31:14

+0

感谢您的帮助和耐心。我见过的GC性能计数器,并没有在GC上花费的时间的低%,但是我需要索姆帮助找出下一个数据: #Bytes在所有堆1115176000 #GC处理845000 #induce GC 5.0 看起来GC.Collect()的调用没有必要,但是对象(图像和位图)的空指定是,因为当它们被忽略时,已使用的内存保持在〜234MB直到应用程序关闭。 – Mario 2009-08-26 18:06:46

1

通常,内存应该最终根据需要自动释放。

但是,为了实现这一点,您需要确保该对象真正未被使用:任何地方都不可能存在对该对象的引用,包括“不再使用”的引用。所以,特别是,如果将WriteableBitmap和原始BitmapSource放置在长寿命类的变量中,它们将不会在容器被释放之前被释放。另外,WPF使用保留的GFX模型:当你渲染时,你实际上只是在上存储指令如何来渲染。关于如何渲染位图的“说明”包括对位图的引用 - 所以如果你曾经渲染过大的位图,那么一段时间(至少与屏幕上的时间相同 - 即使屏幕上的版本很小),那些图像将被保留。

在实践中;只在需要它们的地方存储对这些位图的引用,并且如果它们所处的上下文是长期存在的(一个长方法调用,或者一个方法调用通过引用位图或者一个long-当他们不再需要时,将它们设置为null。

没有必要手动释放内存; GC.Collect()应该是多余的。作为一个经验法则,在基准测试期间只能使用GC.Collect来获取内存消耗的指示和/或以干净的版本开始。总体性能通常通过调用GC.Collect()来降低。