【发布时间】:2017-10-14 21:37:19
【问题描述】:
我正在使用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 堆已正确清除,但非托管内存继续增长。
【问题讨论】:
-
@Downvoter,需要解释一下吗?
-
您是假设存在内存泄漏还是真的遇到了 OutOfMemoryException ?我已经更新了我的答案。顺便说一句,我没有投反对票。
-
你怎么知道是RenderTargetBitmap有内存泄漏? viewBox 元素怎么样?在问这个问题之前,你绝对应该使用内存分析器。
-
@Clemens 我使用了内存分析器。该视图框元素被缓存,并且在该渲染调用之前和之后检查内存使用情况表明这是内存跳跃的地方。
-
@CharithJ 我确实遇到了 OutOfMemory 异常,您可以在调试器中看到内存使用量猛增。
标签: c# wpf memory-management memory-leaks rendertargetbitmap