2015-01-05 70 views
1

我正在使用下面的代碼捕獲桌面快照。自動清理非託管內存

using System; 
using System.Drawing; 
using System.Runtime.InteropServices; 
using System.Windows.Forms; 
using System.IO; 

namespace SMSServer 
{ 
    class CaptureDesktop 
    { 
     // P/Invoke declarations 
     [DllImport("gdi32.dll")] 
     static extern bool BitBlt(IntPtr hdcDest, int xDest, int yDest, int 
     wDest, int hDest, IntPtr hdcSource, int xSrc, int ySrc, CopyPixelOperation rop); 
     [DllImport("user32.dll")] 
     static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDc); 
     [DllImport("gdi32.dll")] 
     static extern IntPtr DeleteDC(IntPtr hDc); 
     [DllImport("gdi32.dll")] 
     static extern IntPtr DeleteObject(IntPtr hDc); 
     [DllImport("gdi32.dll")] 
     static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight); 
     [DllImport("gdi32.dll")] 
     static extern IntPtr CreateCompatibleDC(IntPtr hdc); 
     [DllImport("gdi32.dll")] 
     static extern IntPtr SelectObject(IntPtr hdc, IntPtr bmp); 
     [DllImport("user32.dll")] 
     public static extern IntPtr GetDesktopWindow(); 
     [DllImport("user32.dll")] 
     public static extern IntPtr GetWindowDC(IntPtr ptr); 

     private static string filePath = Directory.GetCurrentDirectory() + @"\CurrentImage.png"; 
     public void CaptureDesktopAsImage() 
     { 
      Size sz = Screen.PrimaryScreen.Bounds.Size; 
      IntPtr hDesk = GetDesktopWindow(); 
      IntPtr hSrce = GetWindowDC(hDesk); 
      IntPtr hDest = CreateCompatibleDC(hSrce); 
      IntPtr hBmp = CreateCompatibleBitmap(hSrce, sz.Width, sz.Height); 
      IntPtr hOldBmp = SelectObject(hDest, hBmp); 
      bool b = BitBlt(hDest, 0, 0, sz.Width, sz.Height, hSrce, 0, 0,   CopyPixelOperation.SourceCopy | CopyPixelOperation.CaptureBlt); 
      Bitmap bmp = Bitmap.FromHbitmap(hBmp); 
      SelectObject(hDest, hOldBmp); 
      DeleteObject(hBmp); 
      DeleteDC(hDest); 
      ReleaseDC(hDesk, hSrce); 
      bmp.Save(filePath); 
      bmp.Dispose();    
     } 
    } 
} 

一切工作正常,但內存消耗太高。迅速增加。在使用JetBrains dotMemory分析應用程序時,我發現這是由於上述代碼造成的。我還看到,在方法結束之前,會調用Dispose()來刪除分配。內存消耗仍然很高。

如何改善上述代碼修復內存泄漏?有任何想法嗎?

+2

我無法在Win 7桌面上重現此操作。如果我在一個小型測試應用程序中快速捕獲我的桌面(2560x1600),則報告的託管內存將在1.5 MB和5 MB之間反彈。如果我添加一個對'GC.Collect()的調用,它在1.7 MB左右保持穩定。任務管理器提交大小報告的總內存以及使用中的GDI對象數量也保持穩定。 – dbc

+1

是否有機會通過中途拋出異常,從而跳過釋放內存? – dbc

+0

忘記提及我調用CaptureDesktopAsImage()方法,如在此問題的服務器部分中所寫:http://stackoverflow.com/questions/27756389/c-sharp-stream-desktop-activity。就我測試而言,不會引發異常 – kunaguvarun

回答

0

嘗試以下解決方案,可能是它有助於 null分配爲您unmanged對象,然後處理它..

使用下面的清理代碼

GC.Collect(); 
GC.WaitForPendingFinalizers(); 
Marshal.FinalReleaseComObject(<your Unmanaged Object>); 

如果有任何目標有着密切的()和open()方法,然後在釋放Com對象之前提及close()..

希望這有助於。

+0

謝謝您概述步驟。正如在上面的評論中提到的那樣,我應該在什麼地方調用GC.Collect()? – kunaguvarun

+1

完成Interop任務後,可能會在bmp.Save(filePath)之下; bmp.Dispose(); –

+0

謝謝你。 GC.Collect()確實解決了這個問題 – kunaguvarun