WinFormsでは、イベントはデリゲート(Event)とVisual Basicの特別な構文— AddHandler および RemoveHandler を介して実装されます。
AddHandler 演算子を使用して行われます。RemoveHandler を使用して行われ、常に正確に対象のハンドラーと一致させることが重要です。例:
AddHandler Button1.Click, AddressOf Button1_Click Sub Button1_Click(sender As Object, e As EventArgs) MessageBox.Show("ボタンが押されました!") End Sub ' アンシブスクリプションのために: RemoveHandler Button1.Click, AddressOf Button1_Click
ウィンドウを閉じたりオブジェクトを破棄したりする際には、必ずイベントからアンシブスクリプションを行い、メモリリークを防ぐ必要があります。ガーベジコレクターはデリゲートの参照が存在する間、オブジェクトを削除しません。
Q: イベントのサブスクライバーオブジェクトを破棄する際にRemoveHandlerを呼び忘れたらどうなりますか?
A: もしオブジェクトが他のオブジェクトのイベントにサブスクライブされていて、アンシブスクリプション(RemoveHandler)が行われていなければ、ガーベジコレクターはサブスクライバーのメモリを解放できません。これは、イベントデリゲートを介した強参照が保持されるためであり、メモリリークを引き起こします。
歴史
1. 申請管理ソフトウェアでは、ログオブジェクトが動的に生成されたすべてのフォームのイベントにサブスクライブしていました。フォームを閉じる際にRemoveHandlerが呼ばれず、アプリケーションが動作するにつれてメモリ消費が増加し、オブジェクトがプログラム全体の閉鎖までメモリ内に残っていました。
歴史
2. 教育プロジェクトでは、子フォームを再び開く際にイベントハンドラーをアンシブスクライブするのを忘れていました。その結果、毎回開くたびにイベントが複数回発生し(毎回新しいサブスクライバーが追加され)、アクションが重複して発生し、インターフェースのロジックが混乱しました。
歴史
3. 工業用オペレーターパネルで、検査員がタイマーのイベントにハンドラーをサブスクライブする自動テストを開始しました。テストのたびにオブジェクトは再作成されましたが、サブスクリプションは解除されず、徐々に遅延が進行しました。このことは、イベント使用時のRemoveHandlerの重要性を証明しました。