Perdita di memoria WTF RichTextBox
-
06-07-2019 - |
Domanda
Nella mia applicazione, ho molti RichTextBox che vengono creati dinamicamente in fase di esecuzione. Mi sono reso conto che l'applicazione ha una perdita di memoria, causata dai controlli RichTextBox. Per dimostrare che la memoria perde a causa del controllo ho scritto il seguente metodo di prova:
for (int i = 0; i < 3000; i++)
{
Control rich = new RichTextBox();
pnl.Content = rich;
}
GC.Collect();
GC.WaitForPendingFinalizers();
pnl è un ContentControl dichiarato nel codice Xaml.
Se esegui il seguente codice, puoi vedere che l'utilizzo della memoria sta crescendo rapidamente.
Qualche idea su come risolvere il problema? Ho preso in considerazione la creazione di un pool di oggetti, ma ciò complicherebbe la mia applicazione e piuttosto lo eviterei.
modifica : ho aggiunto una chiamata al garbage collector per dimostrare che gli oggetti non sono garbage collection - non c'è alcun miglioramento nell'uso della memoria con e senza la chiamata al metodo GC collect.
Nota che chiamare rich.Dispose
all'interno del ciclo elimina la crescita dell'utilizzo della memoria.
Soluzione
L'ho trovato altrove e sembra essere corretto per quanto riguarda i miei test.
Quando viene creato un FlowDocument, formattazione relativamente costosa vengono creati anche oggetti contestuali nella sua StructuralCache. Quando tu creare più FlowDocs in un attimo loop, viene creato un StructuralCache per ogni FlowDoc. Chiamiamo Gc.Collect alla fine del loop, sperando di recuperare un po 'di memoria. StructuralCache ha un finalizzatore rilascia questo contesto di formattazione, ma non subito. Il finalizzatore pianifica in modo efficace un'operazione a contesti di rilascio in DispatcherPriority.Background.
Quindi RichTextBox (o FlowDocument) nel caso non perdesse solo in attesa di un thread in background per la pulizia. Quando funziona esattamente chi lo sa. Vorrei che questo avesse appena implementato un metodo di smaltimento che forzasse immediatamente una pulizia.
Altri suggerimenti
Questa non è un'indicazione che la tua applicazione ha una perdita di memoria, è un'indicazione che la tua applicazione sta usando molta memoria . È una perdita se i controlli RichTextBox
non vengono rilasciati ad un certo punto dopo che sono caduti fuori dal campo di applicazione (rilevare perdite di memoria su oggetti gestiti è notoriamente difficile e non dimostrabile).
Un'idea sbagliata comune secondo cui un oggetto che non rientra nell'ambito di applicazione causerà la raccolta dei rifiuti. Questo rende solo idoneo da collezionare. In teoria l'oggetto non può mai essere mai fino al termine dell'applicazione. Il fatto che cresca con RichTextBox
e non con altri controlli non è un'indicazione che c'è una perdita di memoria in RichTextBox
, è solo un'indicazione che utilizza più memoria per istanza rispetto ad altri controlli. Sebbene queste informazioni possano essere utili, non aiutano a determinare se c'è o meno una perdita di memoria.
Abbiamo avuto lo stesso problema con Winforms 2.0 e abbiamo dovuto acquistare un controllo RTF di terze parti. Immagino che Microsoft non si sia preoccupata di ripararlo ...
Questo mi ha risolto il problema: http://blingcode.blogspot.com/2010/10 /memory-leak-with-wpfs-richtextbox.html
In sostanza aggiungi due attributi a ciascun RichTextBox :) :) IsUndoEnabled = " False "
Per quanto riguarda la modifica:
Hai aggiunto le chiamate GC dopo il ciclo termina e sono stati creati tutti i 3000 RichTextBox
.
Anche se concordo sul fatto che sembra strano che il precedente non venga liberato all'interno del loop quando viene sostituito da uno nuovo, è un loop così stretto che il GC probabilmente non ha la possibilità di "fare cose" ; prima che il ciclo termini.
Non credo sia una buona idea (ma dovrebbe essere OK nel codice di test), ma hai provato a spostare le chiamate GC all'interno del loop?