2011-11-09 40 views
1

Iユーザーコントロールのコードの次の行を持っている:ユーザーコントロールは破棄されていない

Application.Current.RootVisual.MouseLeftButtonDown += RootClicked; 

それは親のUserControlは、もはやGCによって収集や破壊された定義されていないだ場合には、 RootClickedイベントは、もはやアクティブになっていなくても起動します。

私は追加しない場合:

Application.Current.RootVisual.MouseLeftButtonDown -= RootClicked; 

を問題はもはや存在しています。

これは何故ですか?明示的にイベントを削除する必要がある機能はありますか?

答えて

3

これは通常の動作であり、.NETのメモリリークの一般的な原因です。

オブジェクトAのインスタンスメソッドをオブジェクトBのイベントにアタッチすると、イベント受信者のリストにAのインスタンスが追加されるため、ガベージコレクタはハンドラを削除するまでオブジェクトAを解放できません。オブジェクトAとオブジェクトBの両方への参照をすべて解放します。 これは予期された正常な動作です。

問題を解決するには、2つの一般的な方法があります。

1)を使用すると、もはやオブジェクトAを必要としないときは、イベントから、オブジェクトAを解除。

2)WPFのように弱いイベントを使用します。 弱いイベントは、通常、WeakReferenceクラスで実装されています。詳細はWeb上で確認できます。

+0

あなたがのMouseLeftButtonDownイベントにサブスクライブし、アンロードイベントハンドラでのMouseLeftButtonDownイベントを構成解除した後

がアンロードイベントにサブスクライブああ甘い、それが確認された:)私はあなたの答えをstackoverflowできるようにマークします。 – tweetypi

1

これは既知の動作ですが、ほとんどの開発者はそれを認識していません。イベントハンドラを手動で削除するよりも、より優雅な(コード集約的な場合)方法でこの制限を回避する方法については、Weak Event Patternを参照する必要があります。

2

何が起こるか: Application.Current.RootVisual.MouseLeftButtonDownイベントは、コントロールが呼び出しに適さないように(そのコントロールはデリゲートによって参照されるため)、コントロールの呼び出しリストのコントロールを保持します。

ソリューション:

... 
Application.Current.RootVisual.MouseLeftButtonDown += RootVisual_MouseLeftButtonDown; 
this.Unloaded += Control_Unloaded; 
... 

void Control_Unloaded(object sender, RoutedEventArgs e) 
{ 
    Application.Current.RootVisual.MouseLeftButtonDown -= RootVisual_MouseLeftButtonDown; 
} 

以上の簡潔な:

Application.Current.RootVisual.MouseLeftButtonDown += RootVisual_MouseLeftButtonDown; 
this.Unloaded += (s, e) => Application.Current.RootVisual.MouseLeftButtonDown -= RootVisual_MouseLeftButtonDown; 
+0

クラスコントロールにアンロードされていません。 – tweetypi

+0

MSDNの文書をチェックしてください:http://msdn.microsoft.com/en-us/library/system.windows.controls.control(v=vs.95)。 aspxどのSilverlightのバージョンを使用していますか? –

+0

hmm私はsilverlight 3.0を使用しているので、私はそれを持っていません。 – tweetypi

関連する問題