2012-01-04 7 views
1

Win-Formアプリケーションを作成するとき、これはVisual StudioによってFormを処理するために生成されるコードです。WinFormsとイベントハンドラ

protected override void Dispose(bool disposing) 
    { 
     if (disposing && (components != null)) 
     { 
      components.Dispose(); 
     } 
     base.Dispose(disposing); 
    } 

これで十分ですか、コントロールがガベージコレクタによって収集されるようにすべてのイベントを登録解除する必要がありますか?

 if (disposing && (components != null)) 
     { 
      myButton.OnClick-= MyFunction; //may be here!! 
      // ... all events used 
      components.Dispose(); 

     } 

答えて

0

いいえ、ガベージコレクタが処理します。フォームインスタンスが配置されてからボタンを配置したため、イベントをもう上げることはできません。イベントハンドラのためにフォームとボタンの間に循環参照がありますが、ガベージコレクタは問題ありません。

+0

これは、すべてのイベントの登録を解除する責任を負いませんか? –

+1

@ハンス・パサント:私の経験上、フォームに影響を与える*イベントの量が多い場合や、あまりにも頻繁に使用されて「予約解除」しない場合、メモリリークが発生します。 – Tigran

+1

はい、そういう意味です。これは、イベント・ソースがイベント・コンシューマーよりも長生きする場合にのみ必要です。フォームとその子コントロールで決して問題はなく、それらはすべて同時に死ぬ。 SystemEventsクラスのイベントは、手動で登録を解除する必要があるイベントの例です。 –

0

これは、多くの場合、close and open操作の対象となる形で、その内部のイベントの膨大な量を使用している場合、それはすべてのイベントの登録を解除する重要です。 Cuaseイベントはリソースを確実に消費します。これはものの中に表示される形で、あるいは今まで表示されませんでした、またはそれがある場合

、のは言わせyuorアプリケーションのMainForm、それはイベントから退会する重要ではありません。

何を、私は個人的に、内部に退会することを行うにはplaceについて、のはClosingオーバーライドとDispose()ない内としましょう。

+0

「Dispose」にいないのはなぜですか? .netでは、クラスがIDisposableを実装するときにインスタンスに対して 'Dispose'を呼び出すだけで、それに代わって動作している他のエンティティが悪い状態にならないようにすることができます。イベントの発行者にとって、放棄されたことはないが、決して購読を取り止めない加入者の存在は、悪い状態です。これは、「IDisposable.Dispose」が防ぐことになっているものです。 – supercat

+0

@supercat:できるだけ早くそれらを取り除き、ユーザーが暗黙的に呼び出さない場合や、コード構成( 'using'文)によって' GC'呼び出しを待たないようにしてください。 'Dispose()'を使うのは有効な解決策です.BTW、私は受け入れられないようにそれを拒否しませんでした。 – Tigran

+0

「Dispose」が呼び出される前にイベントを切断してはならないという意味ではなく、「Dispose」が呼び出される前にイベントが処理されていない場合、「Dispose」はそれらを終了する必要があります。 Finalize()は、イベントを公開するオブジェクトが放棄されてサブスクリプションが表示されるまで呼び出されないので、イベントのクリーンアップには通常役に立たないことに注意してください。また、あるオブジェクトのFinalize()イベントを切断する必要があります。イベントのサブスクリプションはスレッドセーフではありません。 – supercat

2

フォームは、フォームを失効させるエンティティからのすべてのイベントを登録解除する必要があります。フォームがフォームと同じ存続期間を持つエンティティからイベントを登録解除するかどうかは関係ありません。何らかの理由で、通常の教義は、「重要な場合を除いて、登録を解除することについて心配しないでください」と思われます。私はイベントを購読するすべてのオブジェクトをDisposeに登録解除することがよりきれいだと思うでしょうが、残念ながらvb.netもC#もこれを達成するために何らかの遠隔的にクリーンな方法を提供していません。 IDisposableを実装する依存関係では、新しく作成された項目を後でクリーンアップする項目のリストに追加するルーチンで構築をラップすることができます。リスト内のすべてのものに対して単にDisposeを呼び出すだけで、必要なクリーンアップをすべて実行できます。残念なことに、.netの観点からは、イベントに同時に登録して、Action<>,IDisposableなどの退会に使用できるオブジェクトを返す汎用ルーチンを書く良い方法はありません。

関連する問題