位图和hBitmap内存泄漏

时间:2011-10-24 19:22:35

标签: c# .net wpf memory-leaks

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

[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加载最多1 GB,有时甚至更多! DeleteObject(ip)每次调用时都不起作用。当RAM为1 GB或更多时,它会释放或显示内存不足错误。怎么解决这个问题?

1 个答案:

答案 0 :(得分:2)

如果没有探查器的帮助甚至看不到你的其他代码,我几乎可以保证“泄漏”在这里:

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

肯定会很快调用该方法,而不是Dispose() Bitmaps。在您调用每个Bitmap的终结器之后,GC没有时间进行清理,因此内存不足。

完成后,您需要在Dispose()上致电BitmapBitmapSource无论如何都会复制图像数据,因此不需要它。我会试试这个:

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

这当然假设在这个事件处理程序中处理位图是一件有效的事情(即,是否有其他人处理此事件?)您可能希望在{{1}中公开BitmapSource而不是类,以便您可以确保没有其他客户端依赖WebCamEventArgs保持有效。

当然,如果您将API编写为使用。如果没有,你可以编写一个包装器来确保你的代码永远不会真正看到Bitmap,并且只处理WPF图像类型。