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.

¿Fue útil?

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?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top