6

我试图弄清楚如何释放 WriteableBitmap 内存。

在下一段代码中,我用来自“BigImage”(3600 * 4800 px,仅用于测试)的大量数据填充 WriteableBitmap 的后缓冲区如果我注释位图和图像等于 null 的行,则内存它没有发布,应用程序消耗约 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();
}
4

3 回答 3

3

您是否使用 .Net 3.5 SP1 在 Windows XP 上运行测试?如果是这样,那么这是一个已知问题,将在 4.0 中修复。

请参阅 http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/5d88cdf1-e992-4ad4-8f56-b5dbf92dcf1c

于 2009-11-08T10:57:12.273 回答
1

In general, memory should eventually be freed automatically as needed.

However, for that to happen, you need to be sure that the object is truly unused: No references to the object may exist anywhere, including references which "aren't used anymore". So, in particular, if you place your WriteableBitmap and original BitmapSource in variables of a long-lived class, they won't be released until the container is.

Also, WPF uses a retained GFX model: when you render, you're actually just storing instructions on how to render. The "instructions" on how to render a bitmap include a reference to the bitmap - so if you ever render a large bitmap, then for a while (at least as long as it's on screen - even if the version on screen is tiny) those images will be retained.

In practice; store references to these bitmaps only where they are needed, and if the context in which they live is long-lived (a long method call, or a method call generating a closure with a reference to the bitmaps, or a member of a long-lived class) then set them to null once they're no longer needed.

It is not necessary to manually free the memory; GC.Collect() should be superfluous. As a rule of thumb, only use GC.Collect during benchmarking to get an indication of memory consumption and/or to start with a clean slate. Overall performance is generally decreased by calls do GC.Collect().

于 2009-08-26T13:23:01.403 回答
0

在没有设置的情况下强制 GCimage并且不会清理它们,因为它们仍在本地引用,因此被视为根引用。这与GC 如何工作的更多问题无关。bitmapnullWriteableBitmap

如果您不将它们设置为null并且不强制进行垃圾收集,那么一旦方法存在并且发生 GC,它们将被收集。上面建议您自己强制收集,因为您可能会损害性能而不是帮助它。

于 2009-08-26T13:21:54.260 回答