2009-05-05 19 views
4

私は素晴らしいwinforms 2.0アプリケーションを実行しましたが、うまくいっていて、顧客はまだ満足していますが、1つの問題を解決できません。問題は、アプリケーションを数時間使用した後、gdiユーザーのハンドル番号が上昇していて、処理がより多くのオブジェクトとアプリケーションクラッシュを割り当てることができないということです...winformsでgdi/userハンドラのリークが検出されました

私は何も気にせず、いくつかのフォーム、いくつかのモーダルフォーム、いくつかのdatagridviews、たくさんのテーブルレイアウトアウトプットがあります。ラベルやテキストボックスをたくさん追加しています。

私の質問は以下のとおりです。

  • は、任意の「推奨プラクティスは、」ある システムハンドル を検出する方法を実行時にフォーム上のコントロール 通常のシステム(DGV/TLP)
  • を追加/削除についてリーク - 好ましくは、視覚 スタジオと無料のプラグイン (?プロファイラ)のようなものを使用して

答えて

5

グラフィックや窓漢の検出汚れの漏れは非常に困難です。実行時にそれらを見つけるための特定の戦略に関して、私は何かを提案することはできません(私は他の人のことを聞きたいですが!)。

  • ControlクラスのファイナライザがDispose()を呼び出しますが、これは非決定的である:

    は、それらを防止するためとして、ここではリマインダのカップルです。あなたは、ガベージコレクタによってすべてのオブジェクトが確定されることは保証されません。それは可能性が高いですが、それは保証ではありません。

  • 上記に準拠して、フォームは例外です。 Formが非モーダル(Show()ではなく、ShowDialog()を意味する)で表示されている場合、Formがクローズすると確定的にDispose()が呼び出されます。 ShowDialog()で示されるフォームは、制御ハンドルを確定的にクリーンアップするために手動で呼び出されるDispose()を持っている必要があります。
  • この2つのことを念頭において、最も重要なことは、Dispose()を、IDisposableを実装する明示的に作成したすべてのオブジェクトで常に呼び出すことです。これにはForms、Controls、Graphicsオブジェクト、さらにはPenBrushのようなグラフィックスヘルパークラスが含まれます。これらのクラスはすべてIDisposableを実装しており、不要になったらすぐに処分する必要があります。
  • グラフィックユーティリティのクラスをキャッシュしてみましょう。 PenBrushはかなり軽量ですが、ハンドルを取ってしまい、作業が終わったら処分する必要があります。常にそれらを作成するのではなく、それらのオブジェクトのコンストラクタで使用するパラメータを渡してそのオブジェクトを保持できるようにするキャッシュマネージャを作成します。同じパラメータを使用した繰り返し呼び出しでは、1つのインスタンスしか使用できません。定期的に、またはアプリケーションの特定の場所でキャッシュをフラッシュすることができます。

これらのガイドラインに従うと、ハンドルリークが大幅に軽減されます。

+0

アドバイスいただきありがとうございます。 ソースコードのリークをトレース/検出するツール/ VSプラグインをお勧めしますか? – tomo

+0

@tomo、もう一度いいえ、私はそのようなツールを知りません。私はあなたが直面している問題に似た問題を経験していたので、一度はかなり見ていました。それらを解決することは私を上記のヒントに導いたものです。 –

+0

MDIアプリケーションの一部であるフォームにも、手動でDispose()を呼び出す必要があります。閉じるときにフォームが破棄されない場合の条件は、(1)MDIアプリケーションの一部であり、フォームは表示されません。 (2)ShowDialogを使用してフォームを表示したこと。このような場合、ガベージコレクションのためにフォームのすべてのコントロールをマークするには、Disposeを手動で呼び出す必要があります。 –

1

このようなリークを見つけるには、GDIオブジェクト列を持つタスクマネージャを使用することが不可欠であることがわかりました。特定の領域は、呼び出し前に切断してGDIオブジェクトを書き留めてから、疑わしい呼び出しの後で分割して、オブジェクトが適切に解放されているかどうかを判断することができます。

+0

ええ、私はtaskmanagerを使用して問題を検出しましたが、この問題を尋ねる理由は、その問題を解決する方法です。 – tomo

+0

その場合、Adam Robinsonの記事はあなたが問題を解決するのに役立つはずだと思います。 –

0

2つの有用なGDIリーク追跡ツールのソースコードはここで見つけることができます:私は、多くのVisual Studio C++プロジェクトで正常にそれを使用しているlink text

。私は.NETで動作するかどうかはわかりません。