RenderTargetBitmap中的内存泄漏

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RenderTargetBitmap中的内存泄漏相关的知识,希望对你有一定的参考价值。

我正在使用RenderTargetBitmap渲染一组控件以生成PDF。以下代码段是相关部分:

public Drawing.Image RenderPageBitmap()
{
    RenderTargetBitmap bit = null;
    Drawing.Bitmap bmp = null;
    try
    {
        bit = new RenderTargetBitmap(ImageSource.PixelWidth, ImageSource.PixelHeight, 96, 96, PixelFormats.Pbgra32);

        var viewBox = GetPageXaml(); //This method loads some prebuilt XAML from an embedded resource, setting the DataContext as needed.
        var siz = new Size(bit.PixelWidth, bit.PixelHeight);
        viewBox.Measure(siz);
        viewBox.Arrange(new Rect(siz));
        viewBox.UpdateLayout();

        var draw = new DrawingVisual();
        using (var graph = draw.RenderOpen())
            graph.DrawRectangle(new BitmapCacheBrush(viewBox), null, new Rect(siz));

        bit.Render(draw);
        bit.Freeze();

        bmp = new Drawing.Bitmap(bit.PixelWidth, bit.PixelHeight, Imaging.PixelFormat.Format32bppPArgb);

        var data = bmp.LockBits(new Drawing.Rectangle(Drawing.Point.Empty, bmp.Size), ImageLockMode.WriteOnly, Imaging.PixelFormat.Format32bppPArgb);
        {
            bit.CopyPixels(Int32Rect.Empty, data.Scan0, data.Height * data.Stride, data.Stride);
        }
        bmp.UnlockBits(data);

        return bmp;
    }
    catch (Exception)
    {
        bmp?.Dispose();
        throw;
    }
    finally
    {
        bit?.Clear();

        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();
    }
}

即使关注StackOverflow和其他论坛上的其他答案(如清除位图和执行垃圾收集)似乎也无法解决问题。这段代码的每个循环都可以泄漏~100MB的内存,这意味着我很快就达到了32位进程的~2GB限制。

泄密似乎只发生在RenderTargetBitmap.Render方法上,即使DrawingContext.DrawRectangle调用没有明显增加内存使用量。

有什么办法可以解决这个问题吗?

这是通过JetBrains的dotMemory查看的内存使用情况的快照。显然,.Net堆已正确清除,但非托管内存继续增长。

Memory snapshot

答案

删除bit.Freeze();。垃圾收集不会收集冻结的对象。

另一答案

你把Bitmap送回某个地方。完成后,请确保将Dispose实例处理掉。当存在内存泄漏时,你在finally中所做的事情是无用的。如果有参考,GC将不会收集它。

这段代码的每个循环都可以泄漏~100MB的内存,这意味着我很快就达到了32位进程的~2GB限制。

你假设有内存泄漏?可能没有内存泄漏。我会得到一个很好的内存分析工具并测试它。

我使用过ANTS Memory profiler,我发现它很好(它有14天的试用期)。只需执行几次逻辑,如果有任何增长,请查看实例列表。如果是这样,请查看保留图以查看其中的内容。那会告诉你究竟发生了什么。内存泄漏的根本原因有时很难猜测,幸运的是有很好的工具。

以上是关于RenderTargetBitmap中的内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章

45.JVM调优策略常见问题:内存泄漏(年老代堆空间被占满持久代被占满堆栈溢出线程堆栈满系统内存被占满)优化方法:优化目标优化GC步骤优化总结;案例分析(公司系统参数网上给的配置参数)

java自动垃圾回收机制

为啥使用“RenderTargetBitmap”类会使 GDI 句柄数增加?

jvm知识

为什么不取消注册BroadcastReceiver会导致内存泄漏

关于LOH(Large Object Heap)及内存泄漏