Question

Dans mon application, de nombreux RichTextBox sont créés de manière dynamique au moment de l'exécution. J'ai réalisé que l'application présentait une fuite de mémoire, provoquée par les contrôles RichTextBox. Pour prouver que la mémoire fuit à cause du contrôle, j’ai écrit la méthode de test suivante:

for (int i = 0; i < 3000; i++)
        {
            Control rich = new RichTextBox();
            pnl.Content = rich;
        }
GC.Collect();
GC.WaitForPendingFinalizers();

pnl est un ContentControl déclaré dans le code Xaml.
Si vous exécutez le code suivant, vous pouvez constater que l’utilisation de la mémoire augmente rapidement.

Des idées pour résoudre le problème? J'ai envisagé de créer un pool d'objets, mais cela compliquerait mon application et je l'éviterais plutôt.

Modifier : j'ai ajouté un appel au ramasse-miettes pour démontrer que les objets ne sont pas ramassés. Il n'y a aucune amélioration de l'utilisation de la mémoire avec et sans l'appel de la méthode de collecte du GC. Notez que l'appel de rich.Dispose dans la boucle élimine la croissance de l'utilisation de la mémoire.

Était-ce utile?

La solution

Je l'ai trouvé ailleurs, et cela semble être correct en ce qui concerne mes tests.

  

Quand un FlowDocument est créé,   mise en forme relativement coûteux   les objets de contexte sont également créés pour   dans son StructuralCache. Lorsque vous   créer plusieurs FlowDocs dans un environnement restreint   boucle, un StructuralCache est créé pour   chaque FlowDoc. Laisse vous appelé   Gc.Collect à la fin de la boucle,   dans l'espoir de récupérer de la mémoire.   StructuralCache a un finaliseur   libère ce contexte de formatage, mais   pas immédiatement. Le finaliseur   programme efficacement une opération pour   libérer les contextes à   DispatcherPriority.Background.

Ainsi, RichTextBox (ou FlowDocument) au cas où il ne fuit pas ne fait qu'attendre le nettoyage d'un thread en arrière-plan. Quand ça court exactement qui sait. Je souhaite que cela vienne de mettre en place une méthode d'élimination qui forcerait immédiatement le nettoyage.

Autres conseils

Cela ne signifie pas que votre application a une fuite de mémoire, mais bien que votre application utilise beaucoup de mémoire . C’est une fuite si les contrôles RichTextBox ne sont pas libérés à un moment donné après qu’ils sont tombés hors de portée (la détection des fuites de mémoire sur les objets gérés est notoirement difficile et impossible à démonter).

Une idée fausse répandue selon laquelle un objet tombé hors de la portée de son contenu le ramènera à la poubelle. Cela le rend admissible à collecter. L'objet peut théoriquement jamais être collecté jusqu'à la fin de l'application. Le fait qu’il croisse avec RichTextBox et non avec d’autres contrôles n’indique pas qu’il existe une fuite de mémoire dans RichTextBox , cela indique simplement qu’il utilise plus de mémoire par jour. exemple que d’autres contrôles. Bien que ces informations puissent être utiles, elles ne vous aideront pas à déterminer s’il existe ou non une fuite de mémoire.

Nous avons eu le même problème dans Winforms 2.0 et nous avons dû acheter un contrôle de texte enrichi tiers. Je suppose que Microsoft n’a pas pris la peine de le réparer ...

Cela a corrigé le problème: http://blingcode.blogspot.com/2010/10 /memory-leak-with-wpfs-richtextbox.html

Ajoutez en gros deux attributs à chaque RichTextBox :) :)  IsUndoEnabled = " False "

En ce qui concerne votre modification:

Vous avez ajouté les appels GC après la fin de la boucle et la création de 3 000 RichTextBox

.

Bien que je convienne qu'il semble étrange que la précédente ne soit pas libérée dans la boucle lorsqu'elle est remplacée par une nouvelle, c'est une boucle si serrée que le GC n'obtient probablement pas l'occasion de "faire des choses". ; avant la fin de la boucle.

Je ne pense pas que ce soit une bonne idée (mais cela devrait aller dans le code de test), mais avez-vous essayé de déplacer les appels du GC dans la boucle?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top