1

私は、カスタム(かなり優れた堅牢な)フレームワークが提供されている大規模なプロジェクトに取り組んでおり、フォームとビューを表示するためにそれを使用する必要があります。


新しいStrategyFormが開かれるたびにインスタンス化される抽象クラスStrategyEditor(フレームワークのあるクラスから派生)があります。

StrategyForm(カスタマイズされたウィンドウフレーム)にはが含まれますStrategyEditor
StrategyEditorが含まれていますStrategyTab
StrategyTabが含まれていますStrategyCanvas

これは、実行時に1つのStrategyFormオブジェクトがメモリに割り当てられた場合に作成されるオブジェクトが多数あることを明確にするために、大きなクラスのごく一部です。StrategyForm私のコンポーネントは、コードが私の制御下にない場合を除いて、上記のすべてのクラスを所有しています。


これで、実行時に、ユーザーは多くのストラテジーオブジェクトを開きます(これにより、新しいStrategyFormオブジェクトの作成がトリガーされます)。44の戦略オブジェクトを見ると、アプリケーションによって作成されたUSER OBJECT HANDLES(これ以降はUOHを使用します)は約20k以上に達しますが、レジストリでは、ハンドルのデフォルトの量は10kです。ユーザーオブジェクトについて詳しくは、こちらをご覧ください。さまざまなマシンでテストしたところ、メッセージをポップアップするために開かれる戦略オブジェクトの数が異なることが明らかになりました。あるm / cでは44の場合、別のm/cでは40になる可能性があります。

メッセージのポップアップが表示されたら、アプリケーションの応答が遅いことを意味します。オブジェクトが少なくなると悪化し、ウィンドウフレームとそれに続くオブジェクトの作成は失敗します。

私たちは最初、それは十分なメモリの問題ではないと考えました。しかし、C#で詳細を読むnewと、アプリのメモリが不足すると例外がスローされることを理解するのに役立ちました。これはメモリの問題ではない、と私は感じています(タスクマネージャも1.5GB以上の使用可能なメモリを示しました)。


M/C仕様
Core2Duo 2GHz +
4GB RAM
80GB +ページファイル用の空きディスク容量
仮想メモリセット:4000-6000


私の質問


Q1。これはメモリの問題のように見えますが、そうではないのは間違っていますか?
Q2。これは、(私が考えているように)無料のUOHの枯渇を示しており、ウィンドウハンドルの作成に失敗する結果になっていますか?
Q3。オブジェクトのロードを回避するにはどうすればよいですかStrategyEditor(しきい値を超えて、UOHの現在の使用状況を監視します)。(使用中のUOHの数を取得する方法はすでにわかっているので、そこには行かないでください。)への呼び出しnew StrategyForm()はコンポーネントの制御外であることに注意してください。
Q4。私は少し混乱しています-ユーザーオブジェクトへのハンドルとは正確には何ですか?MSDNは、私たちが作成するオブジェクトについて話しているのですか、それともウィンドウハンドル、カーソルハンドル、アイコンハンドルなどの特定のオブジェクトについて話しているのですか?
Q5。UOHを使い果たす原因は何ですか?(Q4とほぼ同じ)

知識豊富な回答をいただければ幸いです。どうもありがとう!:)

[更新]
Stakxの回答に基づいて、開いているウィンドウはユーザーのみが閉じることに注意してください。これは、あまりにも多くの子ウィンドウが開かれるMDIアプリの状況の一種です。だから、Disposeいつでも呼び出すことはできません。

4

1 に答える 1

2

Q1

同時に作成しようとしているUIコントロールが多すぎるようです。メモリが残っていても、ハンドルが不足しています。簡単ですが、かなり技術的な説明については、以下を参照してください。

Q4

ユーザーオブジェクトは、GUIの一部である任意のオブジェクトであると理解しています。少なくともWindowsXPまでは、Windows UI APIはUSER.DLL(Windowsを構成するコアDLLの1つ)に存在していました。基本的に、UIは「ウィンドウ」で構成されています。ボタン、テキストボックス、チェックボックスなどのすべてのコントロールは、内部的に同じもの、つまり「ウィンドウ」です。それらを作成するには、Win32API関数を呼び出しますCreateWindow。その関数は、作成された「ウィンドウ」(UI要素または「ユーザーオブジェクト」)へのハンドルを返します。

したがって、ユーザーオブジェクトハンドルは、この関数によって返されるハンドルであると想定しています。(Winformsは古いWin32 APIに基づいているため、このCreateWindow関数を使用します。)

Q2

実際、必要な数のUIコントロールを作成することはできません。取得したハンドルはすべてCreateWindow、ある時点で解放する必要があります。Winformsでは、これを行う最も簡単で安全な方法は、usingブロックを使用するか、次のコマンドを呼び出すことDisposeです。

using (MyForm form = new MyForm())
{
    if (form.ShowDialog() == DialogResult.OK) ...
}    

基本的に、すべてをdにするSystem.Windows.Forms.Controlことができ、廃棄する必要があります。Dispose時々、それはあなたのために自動的に行われますが、あなたはそれに頼るべきではありません。DisposeUIは、不要になったときに常に制御します。

Disposeモーダルフォームとモードレスフォームについての注意:

  • モーダルフォーム(で表示ShowDialog)は自動的に破棄されません。上記のコード例に示されているように、自分でそれを行う必要があります。
  • モードレスフォーム(で表示Show)は、ユーザーがいつ閉じるかを制御できないため、自動的に破棄されます。明示的に呼び出す必要はありませんDispose

Q5

UIオブジェクトを作成するたびに、Winformsは内部でを呼び出しますCreateWindow。これがハンドルの割り当て方法です。そして、対応する呼び出しが行われるまで、それらは解放されませんDestroyWindow。Winformsでは、その呼び出しはDisposeanyのメソッドを介してトリガーされますSystem.Windows.Forms.Control(注:これについては確信が持てますが、実際には少し推測しています。100%正確ではない可能性があります。Reflectorを使用してWinformsの内部を見ると、真実が明らかになります。)

Q3

あなたが大量のUIコントロールを作成すると仮定するとStrategyEditor、私はあなたが多くを行うことができるとは思いません。(作成する子コントロールの数に関して)そのコントロールを単純化できない場合は、現在の状況で立ち往生しているように見えます。無限に多くのUIコントロールを作成することはできません。

ただし、StrategyEditor一度に開かれるsの数を追跡することはできます(インスタンス化されるたびにカウンターを増やし、閉じるたびにカウンターを減らします。フォームのFormClosing/FormClosedイベントを使用して後者を追跡できます。コントロールのDispose方法)。次に、同時に開くStrategyEditorの数を固定数、たとえば5に制限できます。制限を超えた場合、コンストラクターで例外をスローして、インスタンスが作成されないようにすることができます。もちろん、コンストラクターStrategyFormからの例外をうまく処理できるかどうかはわかりません...StrategyEditor

public class StrategyEditor : ...
{
    public StrategyEditor()
    {
        InitializeComponent();

        if (numberOfLiveInstances >= maximumAllowedLiveInstances)
            throw ...;
        // not a nice solution IMHO, but if you've no other choice...
    }
}

どちらの場合でも、インスタンス化されるの数を制限することは、StrategyEditor私にとって一時的な修正のように思われ、実際の問題を解決することはできません。

于 2010-04-19T20:41:45.237 に答える