C# 将多个项目添加到画布并使用RenderBitmapTarget进行渲染时WPF泄漏
我在一个服务中诊断了一个漏洞,该服务将多个图像渲染到画布上,然后在最后推出一个位图或PNG(并且多次这样做)。在启动时,该服务将猛增至600MB+然后继续增加,直到它几乎用尽了它所能掌握的一切。一旦启动,它将永远不会减少 我已经使用VS2012 perf mon检测并运行了该服务,并看到在处理完成后,有大量字节数组被放置。我已经尝试过GC清除,看看它是否会将它们清除,但没有效果。使用WinDbg查看它,我可以看到字节数组由一长串项(主要是WPF对象)控制,这些项将图像保存在ram中 我查看了MSDN中所有正在使用的对象,但没有发现任何指出代码运行方式存在问题的内容 我已经整理了一些与服务密切相关的示例代码(为了方便起见减少了一些位)。这称为断开线程(设置为STA)。唯一不同的是服务代码使用MemoryStream加载来自DB的图像,而不是我正在使用的URI。这些流被处理为:C# 将多个项目添加到画布并使用RenderBitmapTarget进行渲染时WPF泄漏,c#,wpf,memory-leaks,C#,Wpf,Memory Leaks,我在一个服务中诊断了一个漏洞,该服务将多个图像渲染到画布上,然后在最后推出一个位图或PNG(并且多次这样做)。在启动时,该服务将猛增至600MB+然后继续增加,直到它几乎用尽了它所能掌握的一切。一旦启动,它将永远不会减少 我已经使用VS2012 perf mon检测并运行了该服务,并看到在处理完成后,有大量字节数组被放置。我已经尝试过GC清除,看看它是否会将它们清除,但没有效果。使用WinDbg查看它,我可以看到字节数组由一长串项(主要是WPF对象)控制,这些项将图像保存在ram中 我查看了MS
public static void TestThread()
{
const int rounds = 50;
const int innerRounds = 50;
var randomiser = new Random(DateTime.Now.Millisecond);
// Simulating some live values
const float scaling = 2.67F;
const int pageWidth = 363;
const int pageHeight = 516;
const int dpi = 96;
// To simulate the live system using multiple images
// This is an list of images of different sizes etc
var imageList = new List<ImageData>
{
new ImageData{Uri = new Uri(@"..."), Height = 2592},
new ImageData{Uri = new Uri(@"..."), Height = 1339},
new ImageData{Uri = new Uri(@"..."), Height = 386},
new ImageData{Uri = new Uri(@"..."), Height = 968},
new ImageData{Uri = new Uri(@"..."), Height = 1952},
new ImageData{Uri = new Uri(@"..."), Height = 1024},
};
var proc = Process.GetCurrentProcess();
for (var i = 0; i < rounds; ++i)
{
var canvas = new Canvas();
canvas.BeginInit();
canvas.SnapsToDevicePixels = false;
canvas.UseLayoutRounding = false;
canvas.Width = pageWidth;
canvas.Height = pageHeight;
canvas.Background = Brushes.White;
for (var j = 0; j < innerRounds; ++j)
{
var img = new Image {Stretch = Stretch.Fill};
var bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
var imageNo = randomiser.Next(0, imageList.Count - 1);
bitmapImage.UriSource = imageList[imageNo].Uri;
int imageHeight = imageList[imageNo].Height;
bitmapImage.DecodePixelHeight = (int) (imageHeight * scaling * 1.8);
bitmapImage.EndInit();
if (bitmapImage.CanFreeze)
{
bitmapImage.Freeze();
}
var opacityMask = new ImageBrush();
var opactityBitmap = new BitmapImage();
opactityBitmap.BeginInit();
opactityBitmap.CacheOption = BitmapCacheOption.OnLoad;
imageNo = randomiser.Next(0, imageList.Count - 1);
opactityBitmap.UriSource = imageList[imageNo].Uri;
int opacityImageHeight = imageList[imageNo].Height; ;
opactityBitmap.DecodePixelHeight = (int)(opacityImageHeight * scaling * 1.8);
opactityBitmap.EndInit();
if (opactityBitmap.CanFreeze)
{
opactityBitmap.Freeze();
}
opacityMask.ImageSource = opactityBitmap;
img.OpacityMask = opacityMask;
img.Source = bitmapImage;
img.Width = pageWidth * scaling;
img.Height = pageHeight * scaling;
Canvas.SetLeft(img, 0);
Canvas.SetTop(img, 0);
canvas.Children.Add(img);
img.Opacity = 50F;
}
canvas.LayoutTransform = null;
var size = new Size(Math.Max(canvas.Width, 5), Math.Max(canvas.Height, 5));
canvas.Measure(size);
canvas.Arrange(new Rect(size));
canvas.EndInit();
var renderTargetBitmap = new RenderTargetBitmap(pageWidth, pageHeight, dpi, dpi, PixelFormats.Default); //xxx
renderTargetBitmap.Render(canvas);
if (renderTargetBitmap.CanFreeze)
{
renderTargetBitmap.Freeze();
}
System.Drawing.Image imageData;
using (var ms = new MemoryStream())
{
var image = new PngBitmapEncoder();
image.Frames.Add(BitmapFrame.Create(renderTargetBitmap));
image.Save(ms);
imageData = System.Drawing.Image.FromStream(ms);
}
var encoder = Encoder.Quality;
var encoderParams = new EncoderParameters(1);
encoderParams.Param[0] = new EncoderParameter(encoder, 100L);
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();
var codecInfo = codecs.FirstOrDefault(x => x.FormatID == ImageFormat.Png.Guid);
Byte[] bitmapArray;
using (var ms = new MemoryStream())
{
imageData.Save(ms, codecInfo, encoderParams);
bitmapArray = ms.GetBuffer();
}
var filepath = string.Format(@"C:\temp\{0}.png", i);
imageData.Save(filepath, ImageFormat.Png);
var gcMemory = GC.GetTotalMemory(false) / 1024;
Console.WriteLine("Proc mem = {0}KB, GC = {1}KB", (proc.PrivateMemorySize64 / 1024), gcMemory);
}
Console.WriteLine("Exiting");
}
publicstaticvoidtestthread()
{
常数整数轮=50;
内部循环常数=50;
var randomiser=新随机数(DateTime.Now.毫秒);
//模拟某些活动值
恒浮标度=2.67F;
常量int pageWidth=363;
常数int pageHeight=516;
常数int dpi=96;
//使用多个图像模拟实时系统
//这是不同大小的图像列表等
var imageList=新列表
{
新图像数据{Uri=newuri(@“…”),高度=2592},
新图像数据{Uri=newuri(@“…”),高度=1339},
新图像数据{Uri=newuri(@“…”),高度=386},
新图像数据{Uri=newuri(@“…”),高度=968},
新图像数据{Uri=newuri(@“…”),高度=1952},
新图像数据{Uri=newuri(@“…”),高度=1024},
};
var proc=Process.GetCurrentProcess();
对于(变量i=0;ix.FormatID==ImageFormat.Png.Guid);
字节[]位图数组;
使用(var ms=new MemoryStream())
{
保存(ms、codecInfo、encoderParams);
bitmapArray=ms.GetBuffer();
}
var filepath=string.Format(@“C:\temp\{0}.png”,i);
保存(文件路径,ImageFor