2009-08-14 6 views
0

J'ai un contrôle TabControl dans WPF/MVVM qui est lié à une ItemsSource au-dessus d'une ObservableCollection. Chaque onglet possède ses propres collections et liaisons avec des composants tels que Images, Richtextboxes et des zones de saisie utilisateur, et tout semble bien fonctionner. Cependant, j'ai remarqué que chaque fois que je change d'onglet, il utilise environ 100 000 de mémoire système qui ne sont jamais récupérées! Si je garde ctrl-tab bas pour faire défiler tous les onglets, je peux utiliser 200 méga-octets de mémoire en une minute.WPF RichTextBox sélection de l'onglet manger de la mémoire système!

Maintenant - J'ai créé une application WPF vierge avec juste un contrôle de tabulation, et il utilise également de la mémoire pour chaque changement d'onglet (albiet beaucoup moins). Est-ce juste un bug .NET, ou une fonctionnalité? Peut-être qu'il stocke un fil d'Ariane, peut-être son utilisé pour le débogage (bien que j'ai compilé en mode de libération).

Comment récupérer ma mémoire? Ou mieux encore, ne pas perdre la mémoire aux commutations d'onglets?

Répondre

0

Bon conseil, mais à la fin j'ai décidé qu'un bloc de texte lisible était plus utile et plus simple qu'une riche zone de texte. Je n'ai jamais découvert ce qui causait la fuite - mais c'était définitivement dans le code bindablerichtextbox (OnInitialized était appelé chaque fois qu'un onglet passait, ce qui était hors de mon contrôle).

Les fuites ont disparu, et mon application s'exécute plus rapidement en raison de l'utilisation du bloc de texte plus facile à lier.

1

Vous pouvez vérifier s'il reste des gestionnaires d'événements.

Dans le cas où vous avez enregistré un événement dans un autre contrôle, le collecteur garbadge ne collectera pas les objets qui ne sont plus nécessaires, car l'événement est toujours attaché pour ainsi dire.

Donc, si vous avez enregistré quelque part Loaded dans le code derrière

public ParentEditor() 
{ 
    InitializeComponents(); 
    control.Loaded += OnControlLoaded; 
} 

ou en XAML ou ParentControl

<Control Loaded="OnControlLoaded" /> 

Vous avez basiquement deux solutions pour résoudre ce problème:

Solution 1 - Supprimez les gestionnaires d'événements lorsqu'ils ne sont plus nécessaires:

Vous pouvez supprimer ce gestionnaire dans le déchargement du contrôle des parents comme ceci:

public ParentEditor() 
{ 
    InitializeComponents(); 
    control.Loaded += OnControlLoaded; 

    this.Unloaded += OnParentUnloaded; 
} 

void OnParentUnloaded(object sender, RoutedEventArgs e) 
{ 
    //Remove unloaded event 
    this.Unloaded -= OnParentUnloaded; 

    //Remove event from child control 
    control.Loaded -= OnControlLoaded;   
} 

Vous pouvez également utiliser l'événement Déchargé du contrôle des enfants bien sûr .. qui est à vous ..

solution 2 - Utilisation du modèle WeakEvent:

Une autre solution pour des événements serait le modèle WeakEvent, qui contourne ce problème.

Pourquoi implémenter le modèle WeakEvent?

L'écoute d'événements peut entraîner des fuites de mémoire . La technique typique pour écouter un événement est d'utiliser la syntaxe spécifique à la langue qui attache un gestionnaire à un événement sur une source . Par exemple, en C#, cette syntaxe est: source.SomeEvent + = new SomeEventHandler (MyEventHandler).

Cette technique crée une référence forte à partir de la source d'événements vers l'écouteur d'événements .Habituellement, attacher un gestionnaire d'événements pour un écouteur provoque l'écouteur pour avoir un objet durée de vie qui a été influencé par l'objet durée de vie pour la source (sauf si le gestionnaire d'événements est explicitement supprimé). Mais dans certaines circonstances, vous pourriez voulez la durée de vie de l'objet de l'auditeur à contrôler que par d'autres facteurs, comme si elle appartient actuellement à l'arbre visuel de l'application, et non par la durée de vie de la source . Lorsque la durée de vie de l'objet source s'étend au-delà de la durée de vie de l'objet de l'écouteur, le modèle d'événement normal conduit à une fuite de mémoire : l'écouteur est maintenu en vie plus longtemps que prévu.

Dans les deux cas, bonne chance .. son tout à fait difficile de trouver des fuites comme celui que vous rencontrez!

+0

Merci pour les conseils - très utile! Mais avec MVVM, les gestionnaires d'événements ne sont même pas utilisés. Le viewmodel ne sait rien sur le gui, et expose seulement les commandes pour que le gui s'y accroche. – bluebit