2

次のコードで tmpTabPages の有効期間を把握しようとしています。フォームに MyTabControl という名前の空の TabControl があり、NameCollection という文字列のコレクションがあるとします。

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    For Each itm In NameCollection
        Dim tmpTabPage as New TabPage(itm.toString)

        'Add Controls to tmpTabPage

        MyTabControl.TabPages.Add(tmpTabPage)
    Next
End Sub

tmpTabPage のスコープは For/Next ブロックであるため、通常、その有効期間はブロックの最後までですよね? しかし、ブロック外のスコープを持つコレクションに追加されるため、コレクション、またはこの場合は MyTabControl と同じ有効期間を取得しますか? 最後に、MyTabControl.TabPages.Clear を呼び出すと、コレクション内の tmpTabPages は破棄されますか、それともメモリを占有するだけですか?

4

4 に答える 4

5

Control から派生したクラス (TabPage を含む) に関する重要な点は、Dispose() メソッドです。それらは自動ガベージ コレクションの影響を受けません。Winforms は、コントロールのハンドルをコントロール参照にマップする内部テーブルを保持します。そのため、たとえば、プログラムがメイン フォームへの参照を保持していなくても、メイン フォームが突然ガベージ コレクションされることはありません。

TabPage を TabControl のコレクションに追加すると、自動破棄が処理されます。同じことが TabControl にも当てはまり、フォームの Controls コレクションに追加されます。通常の一連のイベントは、プログラムまたはユーザーがフォームを閉じることです。Form クラスは、その子コントロールを繰り返し処理し、その Dispose() メソッドを呼び出します。TabControl は Dispose() メソッドで同じことを行い、タブ ページを破棄します。そのプロセスで Windows ウィンドウが破棄され、そのマッピング テーブルからハンドルが削除され、ガベージ コレクターが最終的にコントロールのマネージ ラッパーを収集できるようになります。

多くの Winforms プログラマーを困らせる厄介な罠があります。親のコレクションからコントロールを削除する場合は、自分で破棄する責任があります。削除しても、自動的に破棄されるわけではありません。Winforms は、コントロールを「パーキング ウィンドウ」という名前の非表示のウィンドウに一時的に再ペアレント化することにより、ネイティブ ウィンドウを存続させます。優れた機能です。コントロールを破棄して再作成することなく、ある親から別の親にコントロールを移動できます。

しかし、そこにあるキーワードは「一時的に」です。次にコントロールの親を変更する場合は、一時的なものです。そのため、駐車ウィンドウから新しい親に移動されます。実際に親を変更しないと、駐車ウィンドウで永遠に生き続けます。プログラムが終了するまでリソースをむさぼり食います。これは、リークとも呼ばれます。既に 10,000 個のウィンドウを作成しているにもかかわらず、Windows が別のウィンドウの作成を拒否すると、プログラムがクラッシュする可能性があります。

ControlCollection.Clear() メソッドは、ここで特に有害です。コントロールは破棄されず、すべてその駐車ウィンドウに移動されます。それが意図されていない場合は、めったにそうではありませんが、自分で Dispose() を呼び出す必要があります。

于 2010-11-16T14:39:14.623 に答える
3

.NET のオブジェクトは、取得する方法がない場合、ガベージ コレクションの対象になります。この場合、コレクションから削除されるか、タブ コントロール自体がコレクションの対象になるまで、コレクションTabPage介して取得する方法があります。TabPages

オブジェクトがガベージ コレクションの対象になったからといって、すぐにガベージ コレクションが行われるわけではありません。ガベージ コレクションは、かなり複雑な経験則に基づいてさまざまなタイミングで実行されます。また、メモリの「世代」が存在するため、予測が難しくなります。 .

しかし、基本的に:

  • コレクションに追加されたオブジェクトが不思議なことに収集され、問題が発生することを心配する必要はありません
  • 通常、オブジェクトが永久にメモリ リークすることを心配する必要はありません。オブジェクトを使用しなくなったときに、そのオブジェクトがコレクションの対象であることを確認するために、いくつかの積極的な手順を実行する必要がある状況は確かにありますが、そのような状況は比較的まれです。(私の経験では、通常、それらは静的変数やイベントに関連しています。)
于 2010-11-16T13:58:21.570 に答える
0

オブジェクト TmpTabPage ではなく、TabPage オブジェクトの参照のみをコレクションに追加します。この場合の tmpTabPage オブジェクトは、メモリを割り当てるためだけに使用します。

于 2010-11-16T14:01:12.223 に答える
0

何かがコントロールへの参照を持っているため、それらは破棄されません。

はい、それらへの参照をコレクションに追加していない場合、ライフタイムは手順の最後までになります。

クリアはコレクションからオブジェクトを削除し、それらへの他の参照がない場合、それらはガベージコレクションされます(あなたが説明した状況にはありません)

于 2010-11-16T13:58:30.237 に答える