位图和hBitmap内存泄漏

本文关键字:泄漏 内存 hBitmap 位图 | 更新日期: 2023-09-27 18:12:29

我用WebCam_Capture.dll从我的网络摄像机捕获图像到WPF中的图像控制。对于每个捕获的帧,我都有一个称为webCam_imageCaptured的事件。每次当我从网络摄像头接收到新的图像时,它都会调用。在这个事件中,我调用LoadBitmap方法来获取hBitmap并接收BitmapSource,以将捕获的图片放入图像控件。下面是这个方法的代码:

[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr handle);
public BitmapSource bs;
public IntPtr ip;
public BitmapSource LoadBitmap(System.Drawing.Bitmap source)
{
   ip = source.GetHbitmap();
   bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(ip, IntPtr.Zero, System.Windows.Int32Rect.Empty,
   System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
   DeleteObject(ip);
   return bs;
}

下面是事件的代码:

private void webcam_ImageCaptured(object source, WebcamEventArgs e)
{
    //_frameImage is Image WPF control.
     _frameImage.Source = LoadBitmap((System.Drawing.Bitmap)e.WebCamImage);   
}

我这里漏了!RAM负载高达1gb,有时甚至更多!DeleteObject(ip)不是每次调用都有效。当RAM为1 GB或更多时,它会释放或显示我内存不足错误。如何解决这个问题?

位图和hBitmap内存泄漏

没有分析器的帮助,甚至没有看到您的代码的其余部分,我几乎可以保证"泄漏"在这里:

_frameImage.Source = LoadBitmap((System.Drawing.Bitmap)e.WebCamImage);

该方法当然是被调用非常快,你不是Dispose()你的Bitmaps。GC将没有时间在您之后进行清理并在每个Bitmap上调用终结器,因此您将耗尽内存。

你需要在完成Bitmap之后调用Dispose()BitmapSource无论如何都会复制图像数据,因此不应该需要它。我想试试这个:

private void webcam_ImageCaptured(object source, WebcamEventArgs e)
{
    using( Bitmap b = e.WebCamImage )
    {
         _frameImage.Source = LoadBitmap((System.Drawing.Bitmap)e.WebCamImage);   
    }
}

这当然假设在这个事件处理程序中处理位图是一个有效的事情(即,其他人处理这个事件吗?)您可能希望在WebCamEventArgs类中公开BitmapSource,这样您就可以确保没有其他客户端依赖于该Bitmap保持有效。

当然前提是你编写了API。如果没有,您可以编写一个包装器,以确保您的代码永远不会实际看到Bitmap,而只处理WPF图像类型。