Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/290.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# RenderTargetBitmap中的内存泄漏_C#_Wpf_Memory Management_Memory Leaks_Rendertargetbitmap - Fatal编程技术网

C# RenderTargetBitmap中的内存泄漏

C# RenderTargetBitmap中的内存泄漏,c#,wpf,memory-management,memory-leaks,rendertargetbitmap,C#,Wpf,Memory Management,Memory Leaks,Rendertargetbitmap,我正在使用RenderTargetBitmap渲染一组控件以生成PDF。以下代码段为相关章节: public Drawing.Image RenderPageBitmap() { RenderTargetBitmap bit = null; Drawing.Bitmap bmp = null; try { bit = new RenderTargetBitmap(ImageSource.PixelWidth, ImageSource.PixelHe

我正在使用
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堆已正确清除,但非托管内存仍在继续增长


位图返回到某个位置。确保处理完位图实例后将其丢弃。当内存泄漏时,您在
finally
中所做的一切都是无用的。如果有引用,GC不会收集它

该代码的每个循环都会泄漏约100MB的内存,这意味着 快速达到32位进程的~2GB限制


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


我用过,我觉得很好(它有14天的试用期)。只需执行您的逻辑几次,然后查看实例列表(如果有任何增长)。如果是这样的话,请查看保留图,看看是什么保留了它。这会告诉你到底发生了什么。内存泄漏的根本原因有时很难猜测,幸运的是,有很好的工具可以做到这一点。

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

内存泄漏发生在非托管内存中。对于
RenderTargetBitmap
s,建议使用该垃圾收集技术。
位图
包含在调用者的using块中。@PeterDuniho
System.Drawing.Bitmap
绝对实现了
IDisposable
:@la:我指的是
RenderTargetBitmap
。您没有显示方法声明,因此我不清楚您描述的代码是否处理不同的
Bitmap
类。我使用了JetBrains的dotMemory,发现非托管内存增长,而托管内存没有增长,这几乎不可能使用profiler@Downvoter,想解释一下吗?你是在假设内存泄漏还是真的遇到了OutOfMemoryException?我已经更新了我的答案。顺便说一句,我没有否决投票。你怎么知道是RenderTargetBitmap内存泄漏?viewBox元素怎么样?在问这个问题之前,你一定要使用内存分析器。@Clemens我用过内存分析器。该viewbox元素被缓存,并且在该render调用之前和之后检查内存使用情况表明内存在那里跳跃。@CharithJ我确实得到了一个OutOfMemory异常,您可以在调试器中看到内存使用量猛增。