[英]Bitmap Graphics CreateBitmapSourceFromHBitmap memory leak
我想在带有WPF的Image
容器中显示Bitmap
。
private void updateImagePreview()
{
Bitmap bmp = new Bitmap(Screen.PrimaryScreen.WorkingArea.Width,
Screen.PrimaryScreen.WorkingArea.Height);
Graphics gr = Graphics.FromImage(bmp);
Image Image_Preview;
while (true)
{
gr.CopyFromScreen(0, 0, 0, 0, new System.Drawing.Size(bmp.Width, bmp.Height));
Image_Preview.Source = loadBitmap(bmp);
}
}
[DllImport("gdi32")]
static extern int DeleteObject(IntPtr o);
public BitmapSource loadBitmap(System.Drawing.Bitmap source)
{
IntPtr ip = source.GetHbitmap();
BitmapSource bs = null;
try
{
bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
ip, IntPtr.Zero, Int32Rect.Empty,
System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
}
finally
{
DeleteObject(ip);
}
return bs;
}
问题是,这会造成巨大的内存泄漏。 泄漏发生在CreateBitmapSourceFromHBitmap
调用上,并在循环时填充内存,直到超出限制为止。 如果我不使用该电话,则泄漏消失。 知道为什么会发生吗?
返回之前,请尝试在BitmapSource
上调用Freeze()
。 似乎有助于释放一些对图像字节的引用。
[DllImport("gdi32")]
static extern int DeleteObject(IntPtr o);
public BitmapSource loadBitmap(System.Drawing.Bitmap source)
{
IntPtr ip = source.GetHbitmap();
BitmapSource bs = null;
try
{
bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
ip, IntPtr.Zero, Int32Rect.Empty,
System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
}
finally
{
DeleteObject(ip);
}
bs.Freeze();
return bs;
}
如果存在内存泄漏,则应首先检查的是是否有任何未处理的一次性对象。
我可以看到您没有同时处理Image和Graphics实例,这可能会导致内存泄漏。
确保在使用结束时处置它们。
例如:在updateImagePreview
方法中
using (Graphics gr = Graphics.FromImage(bmp))
{
....
}
例如:在loadBitmap
方法中
public BitmapSource loadBitmap(System.Drawing.Bitmap source)
{
....
finally
{
DeleteObject(ip);
source.Dispose();
}
return bs;
}
我以某种方式解决了该问题,但我不完全知道如何摆脱该泄漏。 我假设调用导致线程内存泄漏的代码可以解决该问题。 我强烈建议使用注释中提到的流包装器 ,因为仅使用MemoryStream还会导致内存泄漏。 无论如何,下面的代码不会导致所提到的内存泄漏,并且对我来说就像是一种魅力。
Timer takeScreen;
// This is a button to start the screen capturing
private void Button_Play_Click(object sender, RoutedEventArgs e)
{
int fps = 30;
takeScreen = new Timer(o => addNewImage(), null, 0, 1000 / fps);
}
private void addNewImage()
{
using (Bitmap bmp = new Bitmap(System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width, System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height))
{
using (Graphics gr = Graphics.FromImage(bmp))
{
gr.CopyFromScreen(0, 0, 0, 0, new System.Drawing.Size(bmp.Width, bmp.Height));
Image_Preview.Dispatcher.Invoke(new Action(() => Image_Preview.Source = loadBitmap(bmp)));
}
}
}
public BitmapSource loadBitmap(System.Drawing.Bitmap source)
{
BitmapSource bmpf = null;
using (MemoryStream ms = new MemoryStream())
{
using (WrappingStream ws = new WrappingStream(ms))
{
source.Save(ws, System.Drawing.Imaging.ImageFormat.Bmp);
bmpf = BitmapFrame.Create(ws, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
}
}
return bmpf;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.