この質問に基づくこの質問: イベントを含むローカル変数を破棄する方法
誰かが言った: インスタンスに 1 つのイベント ハンドラー、インスタンスの参照カウントが追加されますか? なぜ?
この質問に基づくこの質問: イベントを含むローカル変数を破棄する方法
誰かが言った: インスタンスに 1 つのイベント ハンドラー、インスタンスの参照カウントが追加されますか? なぜ?
リンクされた質問は、Jon Skeet が述べているように、逆になっています。生き続ける唯一のものwatcher
は、おそらく、「ティック」のフィードバックを担当する下位レベルのオブジェクトにイベントを登録する (または登録しない) 独自の内部実装です。-しかし、これは単なる推測です。
ボタンを 2 回クリックすると、2 つの別個の watcher
インスタンスが生成され、それぞれがイベントへの1 つのサブスクライバーを持ちますPositionChanged
(これはたまたま同じインスタンスの同じメソッドです)。
重要なのは、メソッドが終了した後も生き続けているのはサブスクライバーではありません-それは別のものです(実装に埋もれていると思います)。メソッドが終了すると、特定のインスタンスへの参照がスタックから正しくポップされますが、別の参照が保持されているため、CLR の有効な参照カウントはまだ 0 より大きいため、ガベージ コレクションの対象にはなりません。 .PositionChanged
watcher
GeoCoordinateWatcher
watcher
watcher
このため、引き続きPositionChanged
イベントを発生させます。イベント内でウォッチャーの続行を妨げるものは何もないため、ボタンをクリックするたびにウォッチャー インスタンスが作成されて存続するため、メモリ リークが発生している可能性があると推測します。
クラスを1 つだけ保存して使用するかGeoCoordinateWatcher
、イベントを処理するたびにクローズ/破棄/停止する必要があります。
デリゲートは、クラスの特定のインスタンス (静的メソッドの場合は型自体) の特定のメソッドへの参照を保持します。イベントをサブスクライブすると、イベント パブリッシャーが、サブスクリプションのデリゲートを介してサブスクライバー インスタンスへの参照を誤って保持してしまいます。
明らかに、静的メソッドをイベント ハンドラーとして登録すると、インスタンスがないため、この参照カウントは取得されません。
サブスクライバーが存続期間が短く、イベント パブリッシャが存続期間が長い場合、サブスクライブを解除しないと、メモリ リークが発生する可能性があります。サブスクライバーが GC の資格を得たいと考えているとします。これは、どこかのイベントに対するアクティブなサブスクリプションがあり、そのオブジェクトがまだ生きているため、そのサブスクリプション リストから削除されるまで適格ではありません。
GeoCoordinateWatcher.Startを呼び出すと、新しいタスクが開始されます。変数のようにコード内で宣言されていても、local
関数のスコープの終了後も引き続き有効です。
関数から3 番目の部分を開始する場合のように、これについて考えることができますprocess
。関数のスコープはなくなりましたが、プロセスはまだ生きています。
提供されたリンクで、ボタンを 2 回クリックすると、2 つの異なるインスタンスが同じイベント ハンドラーGeoCoordinateWatcher
によって処理されます。そのため、イベント ハンドラは の 2 つの異なるインスタンスから 2 回呼び出されます。GeoCoordinateWatcher
デリゲート オブジェクトを作成すると、Method
およびTarget
プロパティが含まれます。Targetプロパティは、メソッドが呼び出されるコンテキストを持つオブジェクトを指しますTarget
(最初のパラメーター、別名this
)。
特定の状況下では、デリゲート オブジェクトへの参照がアクティブになり、Target
インスタンスが GC されなくなります。これは通常、プラグイン/アドインベースのアプリケーション、またはその他の種類の遅延バインド状況がある場合、またはデリゲートを使用して多くの作業を行っており、デリゲート オブジェクトがコレクションに格納されている場合、または静的フィールドがある場合に発生します。デリゲート オブジェクトを使用する (静的フィールドは収集されないため) など。
ガベージ コレクションは「循環参照」の問題の影響を受けないことに注意してください。オブジェクトが「有用」と見なされるには、現在のスタックから到達可能である必要があります。