WPF可写位图存在内存泄漏问题吗?

7

我正在尝试找出如何释放WriteableBitmap的内存。

在下一段代码中,我使用“BigImage”(3600 * 4800像素,仅用于测试)的大量数据填充WriteableBitmap的后台缓冲区。 如果我注释掉将位图和图像赋值为null的行,则其内存不会被释放,即使不再使用Image和bitmap!

正如您在代码末尾所看到的,需要调用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();
}

https://dev59.com/AknSa4cB1Zd3GeqPQLON#2422496 - nyxtom
3个回答

3

2

通常情况下,内存应该会随着需要而自动释放。

但是,为了实现这一点,您需要确保对象真正没有被使用:任何地方都不能存在对该对象的引用,包括“不再使用”的引用。因此,特别是如果您将WriteableBitmap和原始BitmapSource放在长期存在的类的变量中,则它们将一直保留,直到容器被释放。

此外,WPF使用保留的GFX模型:当您进行渲染时,实际上只是存储有关如何进行渲染的指令。渲染位图的“指令”包括对位图的引用-因此,如果您渲染大型位图,则在一段时间内(至少与屏幕上的版本一样长-即使屏幕上的版本很小),这些图像将被保留。

实践中,仅在需要时将这些位图的引用存储在其所需的位置,并且如果它们所处的上下文是长期存在的(长方法调用或生成带有对位图引用的闭包的方法调用或长期存在的类的成员),则在不再需要它们时将它们设置为null。

不需要手动释放内存;GC.Collect()应该是多余的。作为经验法则,在基准测试期间使用GC.Collect()仅用于获取内存消耗的指示和/或以干净的状态开始。总体性能通常会因调用GC.Collect()而降低。


0

如果不将imagebitmap设置为null,强制进行GC是无法清除它们的,因为它们仍然被本地引用,并且被视为根引用。这与WriteableBitmap无关,而更多地涉及到GC的工作原理。

如果您不将它们设置为null,也不强制进行垃圾回收,那么它们将在方法存在并发生GC时被收集。这比自己强制进行垃圾回收更推荐,因为您可能会损害性能,而不是帮助它。


谢谢你们两位的帮助。问题在于垃圾回收器似乎无法回收图像和位图使用的内存。如果我注释掉它们被赋值为null的行,并且一旦方法执行完成,整个应用程序所使用的内存仍然是约234 MB。看起来这是一个非常麻烦的行为。再次感谢。 - Mario
剩余多久?你确定垃圾回收器正在尝试回收吗?打开perfmon并观察GC计数器,以查看它是否正在尝试回收。如果没有,那么你就不用担心——没有内存压力,因此不需要GC。 - Kent Boogaart
感谢您的帮助和耐心。我看到了GC性能计数器,并且在GC中花费的时间很少,但是我需要帮助弄清楚下一个数据:#所有堆中的字节数 1,115,176,000 #GC句柄 845,000 #引发GC 5.0 似乎不需要调用GC.Collect(),但是两个对象(图像和位图)的null分配是必要的,因为当它们被省略时,使用的内存保持在约234MB,直到应用程序关闭。 - Mario
为了进行垃圾回收,对于图像的引用必须被覆盖(例如通过空引用),或者必须不再存在(比如说当方法结束时)。垃圾收集器并不是确定性的 - 不要担心除了这些基本规则之外的东西。如果内存可以通过显式的GC.Collect()释放,那么你就没问题了 - 让垃圾收集器决定时间,并在遇到内存问题时加以处理。 - Eamon Nerbonne

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接