WPF RichTextBox pérdida de memoria
-
06-07-2019 - |
Pregunta
En mi aplicación, tengo muchos RichTextBoxes que se crean dinámicamente en tiempo de ejecución. Me di cuenta de que la aplicación tiene una pérdida de memoria, que es causada por los controles RichTextBox. Para demostrar que la memoria pierde debido al control, escribí el siguiente método de prueba:
for (int i = 0; i < 3000; i++)
{
Control rich = new RichTextBox();
pnl.Content = rich;
}
GC.Collect();
GC.WaitForPendingFinalizers();
pnl es un ContentControl que se declara en código Xaml.
Si ejecuta el siguiente código, puede ver que el uso de la memoria está creciendo rápidamente.
¿Alguna idea de cómo resolver el problema? Pensé en crear un grupo de objetos, pero esto complicaría mi aplicación, y prefiero evitarlo.
edit : agregué una llamada al recolector de basura para demostrar que los objetos no son recolectados, no hay mejora en el uso de la memoria con y sin la llamada al método de recolección de GC.
Tenga en cuenta que llamar a rich.Dispose
dentro del bucle elimina el crecimiento del uso de memoria.
Solución
Encontré esto en otro lugar, y parece ser correcto en lo que respecta a mis pruebas.
Cuando se crea un FlowDocument, formato relativamente costoso los objetos de contexto también se crean para en su StructuralCache. Cuando tú crear múltiples FlowDocs en un apretado bucle, se crea un StructuralCache para cada FlowDoc. Vamos a llamar Gc.Recoge al final del ciclo, con la esperanza de recuperar algo de memoria. StructuralCache tiene un finalizador lanza este contexto de formato, pero no inmediatamente. El finalizador efectivamente programa una operación para liberar contextos en DispatcherPriority.Background.
Entonces, el RichTextBox (o FlowDocument) en caso de que no esté goteando solo espera en un hilo de fondo para la limpieza. Cuando se ejecuta exactamente quién sabe. Desearía que esto solo implementara un método de eliminación que forzaría una limpieza de inmediato.
Otros consejos
Esto no indica que su aplicación tenga una pérdida de memoria, es una indicación de que su aplicación está usando mucha memoria . Es una fuga si los controles RichTextBox
no se liberan en algún momento después de que se han salido del alcance (detectar fugas de memoria en objetos administrados es notoriamente difícil y no se puede probar).
Una idea errónea común de que un objeto que cae fuera del alcance hará que se recolecte basura. Esto solo hace que sea elegible para ser recopilado. El objeto puede teóricamente nunca ser recogido hasta que la aplicación finalice. El hecho de que crezca con RichTextBox
y no con otros controles no es una indicación de que haya una pérdida de memoria en el RichTextBox
, es solo una indicación de que usa más memoria por instancia que otros controles. Si bien esta información puede ser útil, no ayuda al determinar si hay una pérdida de memoria o no.
Tuvimos el mismo problema en winforms 2.0 y tuvimos que comprar un control de texto enriquecido de terceros. Supongo que Microsoft no se molestó en arreglarlo ...
Esto me solucionó el problema: http://blingcode.blogspot.com/2010/10 /memory-leak-with-wpfs-richtextbox.html
Básicamente agregue dos atributos a cada RichTextBox :) :) IsUndoEnabled = " False "
Con respecto a su edición:
Ha agregado las llamadas GC después de que finalice el bucle y se hayan creado los 3000 RichTextBox
.
Si bien estoy de acuerdo en que parece extraño que el anterior no se libere dentro del bucle cuando se reemplaza por uno nuevo, es un bucle tan estrecho que el GC probablemente no tenga la oportunidad de "hacer sus cosas" ; antes de que finalice el ciclo.
No creo que sea una buena idea (pero debería estar bien en el código de prueba), pero ¿ha intentado mover las llamadas del GC dentro del bucle?