我想在Bitmap
容器中使用WPF显示Image
。
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
调用时发生泄漏并在循环时填充内存,直到超出限制。如果我不使用该呼叫,则泄漏消失。知道为什么会这样吗?
答案 0 :(得分:0)
在返回之前,请尝试在Freeze()
上致电BitmapSource
。它似乎有助于释放对图像字节的一些引用。
[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;
}
答案 1 :(得分:0)
如果你有内存泄漏,你应该检查的第一件事是,是否有任何Disposable对象没有被处理。
我可以看到你没有处理可能导致内存泄漏的Image和Graphics个实例。
确保在使用结束时将它们丢弃。
例如:updateImagePreview
方法
using (Graphics gr = Graphics.FromImage(bmp))
{
....
}
例如:loadBitmap
方法
public BitmapSource loadBitmap(System.Drawing.Bitmap source)
{
....
finally
{
DeleteObject(ip);
source.Dispose();
}
return bs;
}
答案 2 :(得分:0)
我以某种方式解决了它,但我并不知道如何摆脱这种泄漏。我假设调用导致线程内存泄漏的代码以某种方式修复了这个问题。我强烈建议使用注释中提到的stream wrapper,因为仅使用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;
}