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.

È stato utile?

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?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top