Question

J'utilise plusieurs comportements Blend et déclencheurs sur un contrôle de silverlight. Je me demande s'il existe un mécanisme pour détacher automatiquement ou faire en sorte que OnDetaching () est appelée pour un comportement ou d'un déclencheur lorsque la commande n'est plus utilisé (par exemple retiré de l'arbre visuel).

Mon problème est qu'il ya une fuite de mémoire gérée avec le contrôle en raison de l'un des comportements. Le comportement est abonnée à un événement sur un objet à long terme dans la dérogation OnAttached () et devrait être le désabonnement de cet événement dans le OnDetaching () ont priorité pour qu'il puisse devenir un candidat pour la collecte des ordures. Cependant, OnDetaching () ne semble jamais s'appeler quand je retire le contrôle de l'arbre visuel ... la seule façon que je peux obtenir que cela se produise est en détachant explicitement les comportements problématiques avant de retirer le contrôle et il est correctement collecté les déchets .

En ce moment, ma seule solution était de créer une méthode publique dans le code-behind pour le contrôle qui peut passer et se détacher des comportements connus qui pourraient causer des problèmes de collecte des ordures. Il appartiendra au code client de savoir appeler cela avant de retirer le contrôle du panneau. Je ne aime pas vraiment cette approche, donc je suis à la recherche d'une certaine façon automatique de faire ce que je donne sur ou une meilleure suggestion.

public void DetachBehaviors()
{
     foreach (var behavior in Interaction.GetBehaviors(this.LayoutRoot))
     {
          behavior.Detach();
     }

     //continue detaching all known problematic behaviors on the control....
}
Était-ce utile?

La solution

Qu'est-ce que vous avez vraiment besoin dans ce cas ne sont pas un moyen de détacher automatiquement, mais veiller à ce que la référence détenue par l'objet à vie longue ne garde pas le comportement (et donc tout le reste, il a une référence à) d'être des déchets collectés.

Ceci est acheived en mettant en œuvre un modèle de médiateur. Le concept est que vous ne donnez pas l'objet à long terme un délégué avec une référence à votre Behaviour, au lieu de créer une classe de médiateur en tant qu'intermédiaire entre les deux. Le médiateur se fixe à l'événement des objets longue durée de vie et est titulaire d'un WeakReference au comportement. Lorsque l'objet long vécu déclenche l'événement les chèques de médiateur que le WeakReference est encore en vie, si les appels si une méthode sur elle pour transmettre l'événement. Si, lorsque l'événement se produit le médiateur constate que le WeakReference est plus en vie, il détache son gestionnaire d'événements de l'objet à long vécu.

Par conséquent, il n'y a rien arrêter le comportement et tout le reste d'être impliqué ordures collectées tous les thats gauche est une très petite instance de médiateur avec une référence morte encore attaché à l'objet de longue durée. Étant donné que ces médiateurs sont minuscules, ils ne représentent pas un réel problème et même ceux disparaîtront la prochaine fois que l'événement se déclenche.

Heureusement, vous n'avez pas à construire ce genre de choses vous-même d'autres l'ont déjà fait. Il est appelé le WeakEventListener. Ce blog: Mise en évidence d'une "contribution faible"; Les améliorations rendent la prévention des fuites de mémoire avec WeakEventListener encore plus facile! a une excellente série de liens sur le sujet.

scroll top