2013-07-18 112 views
8

私のVB.Netアプリケーションの1つで、アプリケーションの実行中にエラーが発生しています。このエラーは常に起こるわけではありません。だから私はエラーを再現することもできません。エラーを再現する正確なシーケンスもありません。vb.netアプリケーションのOutOfMemoryException

スタック: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(メッセージ& M)System.Windows.Forms.Control.WndProcで (メッセージ& M)System.Windows.Forms.ScrollableControl.WndProcで (メッセージ& M) で.Windows.Forms.ToolStrip.WndProc(メッセージ& m)at System.Windows.Forms.StatusStrip.WndProc(メッセージ& m) at System.Windows.Forms.Control.ControlNativeWind System.Windows.Forms.Control.ControlNativeWindow.WndProcでow.OnMessage(メッセージ& M) System.Windows.Forms.NativeWindow.Callbackで(メッセージ& M) (のIntPtr hWndは、MSGのInt32、のIntPtr WPARAM、LPARAMのIntPtr)

エラーの説明:

MyApplication_UnhandledException

このエラーの後、私は

、というメッセージを取得

ビットマップを作成するためのメモリが不足しています。 1つまたは複数のアプリケーションを閉じて、利用可能なものを増やします。

アプリケーションのメモリ使用量を確認したところ、それほど高くありませんでした。このエラーは繰り返し表示されません。では、このエラーのトラブルシューティング方法を教えてください。どのように解決することができますか? .Netメモリプロファイラとredgateメモリプロファイラを使用してアプリケーションの実行を確認しました。

以下は、管理されていないメモリ使用量のスクリーンショットです。これらの値が高いかどうかは私には分かりません。

UPDATE:

私はエラーがGDIオブジェクトをagain.checked持って、それが9998.Soエラーが高いGDIによるものであったobjects.Now質問solve.Thenする方法です私はGDIViewを使用し、チェックしました。そのツールで私はペン2954ブラシ5918フォント90ビットマップ13などGDI合計9998 ペンとブラシは何ですか?私のコードでは、私はブラシやペンを使用していません(私は 'ペン'と 'ブラシ'のコードを検索しましたが、何も取得しませんでした)ので、この助けてください

+0

ツールチップには何を割り当てますか? – Tigran

+1

コードを表示できますか?好ましくは、ビットマップで動作する部分ですか? – Ryan

+1

明らかに唯一のことは、ActiveXコントロールを非常に重く使用していることです。ガベージコレクタが頻繁に実行されるのを防ぐことができます。 System.DrawingオブジェクトでDispose()を使用しないときに発生する問題の種類。あまりにも多くのハンドルを使い切ったとき、このような爆弾が爆発する。 –

答えて

8

あなたのタスクマネージャメニューに移動して、のプロセスタブに表示する列を選択します。 GDIオブジェクト列を表示することを選択します。あなたのプロセスのGDIオブジェクトの合計が10000に達していることがわかります。これはプロセスの最大値です。

使用されている物理メモリの量ではありません。その意味では、エラーメッセージは非常に貧弱で誤解を招きます。問題は、GDIハンドルが不足していることです。ウィンドウ下の各プロセスは、作成できるGDIハンドルの最大数に制限されています。この制限は現在、1プロセス当たり10000ハンドルです。

あなたの問題がGDIハンドルであると仮定している理由は、コントロールを描画するプロセス中に新しいビットマップを作成しようとしているときに例外がスローされるためです。ビットマップはGDIオブジェクトです。ビットマップを作成すると、そのビットマップにGDIハンドルが使用されます。したがって、その可能性が高い原因です。

標準のToolStripコントロールでエラーが発生しているため、ToolStrip自体のバグではありそうにありません。プログラム内の他の場所にあるGDIハンドルをすべて使い切ってしまった場合、コントロールが描画しようとするとハンドルが残っていないため失敗します。

ペンやビットマップなどのGDIオブジェクトを作成するときはいつでも、それらのオブジェクトを処分する必要があります。 GDIを取得するすべてのGDIクラスはIDisposableインターフェイスを実装します。オブジェクトが破棄されると、その時点でハンドルが自動的に削除されます。しかし、オブジェクトを決して処分しないと、ハンドルは決して削除されず、GDIオブジェクトの数は増加し続けます。あなたがオブジェクトで行われたときにどのIDisposable物を処分する

、あなたは単に例えば、Disposeメソッドを呼び出すことができます。

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

しかし、あなたができるならば、それはのための変数を宣言するためにも良いでしょうUsingブロックとIDisposableオブジェクトは、次のように:Usingブロックで

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

Dispose方法はあなたのために自動的に呼び出されます、自分で明示的に呼び出す必要はありません。 UsingブロックがDisposeを呼び出すよりも優れているのは、Usingブロック内に例外がスローされた場合でも、Disposeメソッドが自動的に呼び出されるためです。 Usingブロックを使用せずに明示的に自分自身を呼び出す場合は、呼び出す必要があるすべての場所を見逃しやすくなります。

コード内の問題領域を見つけるには、デバッガでプログラムを実行し、コードをステップ実行します。 タスクマネージャーを開いたままにし、コードをステップ実行しながらGDIオブジェクト列を表示します。 GDIオブジェクトの列をタスクマネージャーで見ると、新しいGDIオブジェクトが作成されるとカウントが増加することがわかります。この方法を使用すると、問題がどこにあるかを簡単に確認できます。

+1

+1前述のように、Usingブロックは理想的です。 –

+0

どのPCでもエラーが発生した場合、gdiオブジェクトをチェックします。 –

+1

私のアプリケーションでグリッドをクリックしている間、Msflexgridはdisposing.Itがグリッドのクリックごとにgdiオブジェクトを増やしていて解決策を得ました。デバッガでプログラムを実行して問題を解決しました。今問題は解決され、gdiカウントは250〜300。ありがとうございました。 –