fereastra eveniment închis nu eliberează memorie și resurse. Cum de a rezolva scurgeri de memorie în WPF?

Recent am observat o scurgere serioasă de memorie în proiectul meu WPF. Dacă simplificați proiectul, acesta are un formular de autentificare și un formular principal. În forma principală există un control al utilizatorului care este compus din aproximativ 30 de comenzi de utilizator și 3 butoane, un control al utilizatorului care are 3 butoane și o infrarosie de date. Folosesc lucrătorul de fundal pentru a interoga DB la fiecare 30 sec doar pentru datagrid.

După ce am deconectat formularul principal folosind formularul principal.închis și re-lansarea ferestrei de conectare, am observat că de fiecare dată există o creștere de 6-7MB măsurată de profilul de memorie ANTS 7. Chiar dacă am manipulatoare de evenimente neînregistrate, setați variabilele la null și numit GC.Collect (), scurgerea memeorală este în continuare aceeași. Întrebările mele sunt: 1. De ce închiderea ferestrei wpf nu eliberează memoria și resursele? Pot vedea mai multe siruri de caractere (cele mai multe dintre ele sunt din GUI) sunt încă în memorie după fereastra închisă de profilul ANTs. 2. Trebuie să nu înregistrez evenimentele definite de setterul de evenimente pentru resurse? Trebuie să nu înregistrez evenimentele declarate în XAML? 3. De la scurgere de memorie wpf , oamenii au spus că nu ar trebui să folosim GC.Collect (), dar fac a se vedea o îmbunătățire puțin. Să o folosim sau nu?

0

3 răspunsuri

Depinde. Controalele utilizatorilor din wpf nu dispun în mod inerent, deci va trebui să înlocuiți funcționalitatea și să o permiteți în comenzile dvs. cu:

http://msdn.microsoft.com/en-us/library /system.idisposable.dispose.aspx

Dar pentru punctul dvs. de vedere, va trebui să faceți un GC.Collect() cel puțin o dată, așa cum sugerează SlimGG.

În majoritatea cazurilor, apelarea directă a colectorului de gunoi este considerată o practică necorespunzătoare, deoarece nu o numește pentru controlul dvs. specific, ci pentru toate obiectele în așteptare pentru eliminare.

0
adăugat
Am gasit un loc care a cauzat scurgeri de memorie in cod datorita utilizarii DependencyPropertyDescriptor.FromProperty ... AddValueChanged dar fara a inlatura valoarea schimbata. Cu toate acestea, am observat încă scurgeri de memorie în alte ferestre. Sunt de acord că vom apela GC.Collect deoarece există un control al utilizatorului în interiorul controlului utilizatorului. Mulțumiri.
adăugat autor user1424258, sursa

Pauză în depanator și apoi tastați-l în fereastra Imediat:

.load C:\Windows\Microsoft.NET\Framework\v2.0.50727\sos.dll

Calea către sos.dll variază. Modul de a afla calea corectă este să căutați mscorwks.dll în panoul Module. Ori de câte ori este încărcat este calea corectă pentru sos.dll.

Apoi, tastați aceasta:

System.GC.Collect()

That will ensure anything not reachable is collected. Apoi, tastați aceasta:

!DumpHeap -type 

Aceasta vă va arăta un tabel cu toate instanțele existente, cu adrese. Puteți afla ce păstrează un exemplu în viață:

!gcroot 

originally answered by Daniel

0
adăugat

Am avut o problemă similară în timp ce folosesc WindowsFormsHost pentru controlul PictureBox. Fereastra wpf care utilizează controlul WF PictureBox nu a putut fi eliberată pe deplin și de aceea am avut o creștere constantă de ~ 10MB de fiecare dată când am redeschis sub-fereastra. Problema a fost rezolvată de când am început nulirea obiectului WFH pe închiderea ferestrei WPF. Doar asigurați-vă că ați șterge toate controalele WF dacă utilizați astfel.

0
adăugat