3

「ウィンドウ ハンドルの作成中にエラーが発生しました」という実行時エラーが発生します。私の調査によると、このエラーは通常、アプリケーションが Windows の 10,000 ハンドル制限を超えたことを示していることがわかっています。ハンドルが不必要に作成されず、適切に破棄されるようにすることで、エラーに対処する必要があります。

ただし、ウィンドウ ハンドルが作成される原因に関するドキュメントは見つかりません。フォームをインスタンス化するたびにウィンドウ ハンドルが作成されますか? コントロールをインスタンス化するたびに? クラスをインスタンス化するたびに?または何?

軽量 UI アプリケーションの場合、使用するハンドルの数を特に気にする必要はありませんが、グラフィック要素が多いアプリケーションの場合、プログラマはウィンドウ ハンドルの数を制限するための措置を講じる必要があると言えますか? それが「ウィンドウレス コントロール」と「軽量コントロール」のすべてでしょうか。知っておくべきその他の関連する概念はありますか?

これまで、自分のアプリケーションが特に UI を多用しているとは考えていませんでした。ただし、グラフのグリッドは表示されます。各グラフは、複数のコンポーネント コントロールで構成されるユーザー コントロールです。大規模な分析では、コントロールの総数が数千に達する場合があります。このグリッドを保持したいと仮定すると、ハンドルのカウントダウンを維持するために適用できる特定のテクニックはありますか? たとえば、コントロールを「レンダリング」してまだ表示されているが、ウィンドウ ハンドルが不要になる方法はありますか?

-TC

4

2 に答える 2

4

ただし、ウィンドウ ハンドルが作成される原因に関するドキュメントは見つかりません。

これはおそらく、.net が抽象化されているためです。

Win32 の「実際の」世界では、ウィンドウ ハンドルはタイプによって示され、HWNDほとんどすべてのものに与えられます。すべてのボタン、メニューなどにHWND.

実際、それは正しくありません。作成できるオブジェクトのすべてのクラス(C Windows API 内) にはハンドルがあります。通常、各クラスはコントロール全体のみを描画しますが、一部のコントロールは、追加のボタンなど、より複雑なコントロールを描画する場合があります。別のウィンドウ (コントロール) を作成するか、たとえば GDI を使用して描画することができます。

したがって、表示されるすべてが HWND を生成するわけではありませんが、ほとんどの場合は生成されます。

興味深いことに、C/Win32 でコントロールを作成するには、CreateWindow(). すべてが Windowです。

それでは、.net APP に戻ります。依存しているコントロールが、基になるCreateWindow呼び出しを介して多くのオブジェクトを作成する場合、多くのHWND変数を発行し、最終的に一意の識別子を使い果たすことになります。

Mark Russinovich は、Windows の限界に挑む際の実際的な限界について説明しており、アプリケーションの割り当てを故意に使い果たそうとしています。

では、どのようなプログラミング手法がこれを引き起こすのでしょうか? 作成する Window オブジェクトが多すぎます。これは、アプリケーション ウィンドウという意味での実際の Windows に対応していない可能性があります。むしろ、コントロールの量に対応しています。これを回避する唯一の方法は、使用量を減らすか、サードパーティが問題を引き起こしている場合は、一度に表示できる実際の制限に基づいてアプリケーションを設計することです。

別の方法は、サブコントロールを使用するのではなく、サブコントロールを描画する独自のコントロールを作成することです。ただし、これは大変な作業になる可能性があります。

于 2012-04-25T20:36:57.983 に答える
1

つまり、ウィンドウ ハンドルは、インタラクティブなすべての UI 要素に与えられます。すべての実際のウィンドウ、すべてのテキスト ボックス、グリッド セル、ボタン、メニューなど。非対話型コントロールはウィンドウ ハンドルを必要としませんが、適切に記述されていない場合でもウィンドウ ハンドルを使用する可能性があります。

通常、ウィンドウ ハンドルの制限に到達することは非常に困難です。これが発生していて、アプリが特に UI を集中的に使用していない場合、これは通常、ハンドルがリークしていることを意味します。これは、不適切に作成されたビジュアル コンポーネントのライブラリを使用し、必要なときにリソースを解放しない場合に発生する可能性があります。ウィンドウ ハンドルは管理されていないリソースであり、不要になったら解放するように注意する必要があります。たまたまライブラリを使用していてハンドル リークが発生している場合は、ライブラリを変更することをお勧めします。通常は想像以上に難しいので、ガベージ コレクターに強制的にオブジェクトを収集させ、管理されていないすべてのリソースがファイナライザー/デストラクタで解放されることを期待することができます。

GC.Collect();

使用しているコントロールが正しく記述されていない場合、ファイナライザーでもハンドルを解放しない可能性があるため、これが役立つという保証はありません。繰り返しますが、これは悪い習慣ですが、他に選択肢がない場合に役立つ可能性があります。

標準の .NET コントロールのみを使用する場合はClose()、フォームを非表示にするだけでなく、使用後にすべてのフォームを確認してください。これにより、ダイアログ以外のフォームとそのすべてのコントロールが破棄され、それらが標準コントロールである場合、リークは発生しません。ダイアログ フォームは、コードで破棄する必要があります。詳細なドキュメントはこちらです。

于 2012-04-25T20:57:29.607 に答える