0

この質問に基づくこの質問: イベントを含むローカル変数を破棄する方法

誰かが言った: インスタンスに 1 つのイベント ハンドラー、インスタンスの参照カウントが追加されますか? なぜ?

4

3 に答える 3

2

リンクされた質問は、Jon Skeet が述べているように、逆になっています。生き続ける唯一のものwatcherは、おそらく、「ティック」のフィードバックを担当する下位レベルのオブジェクトにイベントを登録する (または登録しない) 独自の内部実装です。-しかし、これは単なる推測です。

ボタンを 2 回クリックすると、2 つの別個の watcherインスタンスが生成され、それぞれがイベントへの1 つのサブスクライバーを持ちますPositionChanged(これはたまたま同じインスタンスの同じメソッドです)。

重要なのは、メソッドが終了した後も生き続けているのはサブスクライバーではありません-それは別のものです(実装に埋もれていると思います)。メソッドが終了すると、特定のインスタンスへの参照がスタックから正しくポップされますが、別の参照が保持されているため、CLR の有効な参照カウントはまだ 0 より大きいため、ガベージ コレクションの対象にはなりません。 .PositionChangedwatcherGeoCoordinateWatcherwatcherwatcher

このため、引き続きPositionChangedイベントを発生させます。イベント内でウォッチャーの続行を妨げるものは何もないため、ボタンをクリックするたびにウォッチャー インスタンスが作成されて存続するため、メモリ リークが発生している可能性があると推測します。

クラスを1 つだけ保存して使用するかGeoCoordinateWatcher、イベントを処理するたびにクローズ/破棄/停止する必要があります。


イベントとサブスクリプションに関する通常の考慮事項は、存続期間の長いオブジェクトをサブスクライブする存続期間の短いオブジェクトに注意することです。

デリゲートは、クラスの特定のインスタンス (静的メソッドの場合は型自体) の特定のメソッドへの参照を保持します。イベントをサブスクライブすると、イベント パブリッシャーが、サブスクリプションのデリゲートを介してサブスクライバー インスタンスへの参照を誤って保持してしまいます。

明らかに、静的メソッドをイベント ハンドラーとして登録すると、インスタンスがないため、この参照カウントは取得されません。

サブスクライバーが存続期間が短く、イベント パブリッシャが存続期間が長い場合、サブスクライブを解除しないと、メモリ リークが発生する可能性があります。サブスクライバーが GC の資格を得たいと考えているとします。これは、どこかのイベントに対するアクティブなサブスクリプションがあり、そのオブジェクトがまだ生きているため、そのサブスクリプション リストから削除されるまで適格ではありません。

于 2012-06-12T12:57:40.853 に答える
0

GeoCoordinateWatcher.Startを呼び出すと、新しいタスクが開始されます。変数のようにコード内で宣言されていてもlocal関数のスコープの終了後も引き続き有効です。

関数から3 番目の部分を開始する場合のように、これについて考えることができますprocess。関数のスコープはなくなりましたが、プロセスはまだ生きています。

提供されたリンクで、ボタンを 2 回クリックすると、2 つの異なるインスタンスが同じイベント ハンドラーGeoCoordinateWatcherによって処理されます。そのため、イベント ハンドラは の 2 つの異なるインスタンスから 2 回呼び出されます。GeoCoordinateWatcher

于 2012-06-12T12:58:42.233 に答える
0

デリゲート オブジェクトを作成すると、MethodおよびTargetプロパティが含まれます。Targetプロパティは、メソッドが呼び出されるコンテキストを持つオブジェクトを指しますTarget(最初のパラメーター、別名this)。

特定の状況下では、デリゲート オブジェクトへの参照がアクティブになり、Targetインスタンスが GC されなくなります。これは通常、プラグイン/アドインベースのアプリケーション、またはその他の種類の遅延バインド状況がある場合、またはデリゲートを使用して多くの作業を行っており、デリゲート オブジェクトがコレクションに格納されている場合、または静的フィールドがある場合に発生します。デリゲート オブジェクトを使用する (静的フィールドは収集されないため) など。

ガベージ コレクションは「循環参照」の問題の影響を受けないことに注意してください。オブジェクトが「有用」と見なされるには、現在のスタックから到達可能である必要があります。

于 2012-06-12T12:59:01.133 に答える