2011-10-24 56 views
2

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

[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或更多时,它会释放或显示内存不足错误。如何解决这个问题?

+0

当你不再需要位图时,你处理位图吗? –

+0

我试过在DeleteObject方法后处理。像这样: source.Dispose();但没有帮助。 –

+1

你确定泄漏实际上在这里吗?你是如何确定的?你有没有使用任何类型的分析器?是否有引用这些BitmapSource对象是陈旧的?你为什么不在使用它后丢弃你的位图?这肯定是(临时)内存泄漏。使用BitmapCacheOptions.OnLoad创建BitmapSource并摆脱位图。 –

回答

2

没有一个分析器的帮助,甚至看到你的代码的其余部分,我几乎可以保证的是,“泄漏”是在这里:

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

这种方法肯定是被称为非常迅速,你是不是Dispose()你的Bitmaps。 GC之后没有时间清理,并在每个Bitmap上调用终结器,因此内存不足。

您需要在完成该操作后致电Dispose()对该Bitmap。无论如何,BitmapSource都会复制图像数据,因此不需要它。我想试试这个:

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

当然,这是假设这个事件处理程序中的位图的处置是做有效的事(即没有任何人处理这个事件?)你可能要暴露在BitmapSourceWebCamEventArgs类,以便您可以确保没有其他客户端依赖该Bitmap保持有效。

那当然如果你写了API来。如果不是的话,你可以编写一个包装器,以确保你的代码永远不会看到一个Bitmap并只处理WPF图像类型。

+0

是的,你是对的。这个图书馆里面有泄漏。它出现在这个事件中。谢谢。 –