2013-07-18 52 views
8

在我的一個VB.Net應用程序中,運行應用程序時出現錯誤。這個錯誤並不總是如此。所以我也無法重現錯誤。也沒有確切的序列來重現錯誤。vb.net應用程序出現OutOfMemoryException

Stack:System.OutOfMemoryException:內存不足。 在System.Drawing.Graphics.FromHdcInternal(IntPtr的HDC) 在System.Windows.Forms.ToolStrip.OnPaint(PaintEventArgs的E) 在System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs的E,Int16的層,布爾disposeEventArgs) 在System.Windows.Forms.Control.WmPaint(消息&米) 在System.Windows.Forms.Control.WndProc(消息&米) 在System.Windows.Forms.ScrollableControl.WndProc(消息&米) 在系統.Windows.Forms.ToolStrip.WndProc(Message & m) at System.Windows.Forms.StatusStrip.WndProc(Message & m) at System.Windows.Forms.Control.ControlNativeWind ow.OnMessage(消息&米) 在System.Windows.Forms.Control.ControlNativeWindow.WndProc(消息&米) 在System.Windows.Forms.NativeWindow.Callback(IntPtr的的HWND,MSG的Int32,IntPtr的WPARAM,IntPtr的LPARAM)

錯誤描述:

MyApplication_UnhandledException

這個錯誤後,我得到一個消息說,

內存不足以創建位圖。關閉一個或多個應用程序以增加可用性。

當我檢查應用程序的內存使用情況並不是那麼高。此錯誤不會重複出現。所以我如何解決這個錯誤。它如何解決? 我使用.Net內存分析器和redgate內存分析器檢查了運行我的應用程序。

下面是非託管內存使用量的屏幕截圖。我不知道這些值是否很高。

UPDATE:

我得到了錯誤again.checked GDI對象,這是9998.So錯誤是由於高GDI objects.Now的問題是如何solve.Then我用GDIView和checked.By那個工具,我得到了筆2954刷5918字體90位圖13等GDI總9998 那麼這些筆和筆是什麼?在我的代碼中,我沒有使用筆刷或筆(我在代碼中搜索「筆」和「筆刷」,但沒有找到任何代碼)。請在此幫助我

+0

你分配給Tooltip的是什麼? – Tigran

+1

你能告訴我你的代碼嗎?最好是一些使用位圖的部分? – Ryan

+1

唯一明顯的是,您使用的ActiveX控件相當重要。這可以防止垃圾收集器經常運行以避免麻煩。您在System.Drawing對象上不使用Dispose()時遇到的麻煩。當你使用了太多的手柄時,它會像這樣炸彈。 –

回答

8

在您的任務管理器 ,請轉到查看菜單以選擇要在進程選項卡中顯示哪些列。選擇你想要顯示的GDI對象列。我相當肯定你會看到你的進程的總GDI對象達到10000,這是任何進程的最大值。

這不是一個多少物理內存正在使用的問題。從這個意義上講,錯誤信息是非常差和誤導。問題是你已經用完了GDI句柄。 windows下的每個進程都被限制爲可以創建的最大數量的GDI句柄。目前每個進程的限制爲10000個句柄。

我假設您的問題是GDI句柄的原因是因爲在繪製控件的過程中嘗試創建新的位圖時引發異常。位圖是GDI對象。創建位圖會爲該位圖使用一個GDI句柄。因此,這很可能是原因。

由於錯誤發生在標準ToolStrip控件中,因此它不太可能是ToolStrip本身的錯誤。在你的程序的其他地方,你更有可能使用了所有的GDI句柄,然後,當控件試圖自己繪製時,它失敗了,因爲沒有句柄。

無論何時您創建GDI對象(如筆和位圖),您都需要確保處置這些對象。所有獲取GDI句柄的GDI類都實現了IDisposable接口。當對象被丟棄時,它們會自動刪除那個點的句柄。但是,如果你永遠不處理這些對象,這些句柄永遠不會被刪除,而且你的GDI對象數量將會持續增長。

處置任何IDisposable的對象,你可以簡單地調用Dispose方法,當你這個對象,例如:

Dim b As New Bitmap("test.bmp") 
'... 
b.Dispose() 

但是,如果可以的話,它甚至更好聲明變量IDisposable對象與Using塊,像這樣:

Using b As New Bitmap("test.bmp") 
    '... 
End Using 

隨着Using塊時,Dispose方法會自動爲你調用,所以你不需要自己明確地調用它。之所以Using塊比你自己調用Dispose更好,是因爲如果在Using塊內拋出異常,Dispose方法仍然會自動調用。如果您自己明確地調用它,並且沒有Using塊,則更容易錯過每個需要調用它的地方。

要在代碼中查找問題區域,請在調試器中運行程序並逐步執行代碼。在您單步執行代碼的同時,將任務管理器打開,顯示GDI對象列。查看任務管理器中的GDI對象列,您將看到在創建新的GDI對象時計數會增加。使用這種方法應該相當容易,看看問題出在哪裏。

+1

+1如上所述,Using塊是理想的。 –

+0

如果我在任何PC中出錯,我會檢查gdi對象。 –

+1

在我的應用程序中點擊網格的時候,Msflexgrid並沒有配置,它增加了每個點擊網格的gdi對象並獲得瞭解決方案。然後我通過在調試器中運行該程序來解決問題。現在問題得到解決,現在gdi count保持在250到300.非常感謝你。 –