2011-10-24 55 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

是的,你是對的。這個圖書館裏面有泄漏。它出現在這個事件中。謝謝。 –