Laden...

Garbage Collection nimmt DockContent nicht mit, wie Referenz finden?

Erstellt von mydani vor 14 Jahren Letzter Beitrag vor 14 Jahren 1.459 Views
M
mydani Themenstarter:in
24 Beiträge seit 2009
vor 14 Jahren
Garbage Collection nimmt DockContent nicht mit, wie Referenz finden?

Hallo,

in einer Anwendung lege ich DockContents an (benutze WeifenLuo.WinFormsUI.Docking), welche die Klasse Form erweitern, und ich gebe diese wieder frei durch einen expliziten Aufruf von .close().
Leider sammelt der GC die Objekte nicht ein und der Speicher bleibt belegt.
Das selbe Spiel bei .dispose().

Wenn es also irgendwo noch Referenzen auf das Objekt gibt weiß ich nicht wo - lässt sich das irgendwie herausfinden, ob Referenzen auf ein Objekt existieren, dass ich mit dispose() freigegeben habe?

Danke!

Gruß,
Daniel

C
52 Beiträge seit 2010
vor 14 Jahren

Wenn du Form.Dispose() aufrufst, werden alle in der Form erzeugten Objekte/Resourcen freigegeben. Damit ist alle bereit zum Abholen durch den GC.

Wo/Wie werden denn die DockContents erzeugt? Wie kommen sie in Form?
Vermutlich haben sie noch irgendwo eine root reference.

49.485 Beiträge seit 2005
vor 14 Jahren

Hallo mydani,

vermutlich hast du das Dock-Control der Controls-Collection des Form hinzugefügt. Dann ist in der Controls-Collection noch eine Referenz enthalten, die du entfernen musst (Remove).

herbivore

M
mydani Themenstarter:in
24 Beiträge seit 2009
vor 14 Jahren

Hallo,

@chrismoe: Das DockContent erzeugt die Objekte, die es benutzt, selbst - es wird nichts anderswo erzeugt, deswegen sollte nach dem Dispose auch alles wieder freigegeben werden.

@herbivore: ich dachte mir schon dass es noch eine Referenz darauf gibt da selbst ein expliziter Start des Garbage-Collectors nur einen kleinen Teil RAM wieder freigibt, weiß aber nicht genau, wie ich herausfinden kann, wer noch eine Referenz auf das DockContent hat.

Aufgebaut ist es wie folgt - es gibt eine mainForm, die enthält das DockPanel.
Dann erzeuge ich 1 bis viele DockContents (die alle von Form erben) - diese lassen sich dann ans DockPanel andocken. Anschließend rufe ich .dispose() der DockContents auf.
In dem Dockpanel gibt es dann keine sichtbare Referenz mehr, hab die ganzen Members durchsucht.

Gruß,
Daniel

49.485 Beiträge seit 2005
vor 14 Jahren

Hallo mydani,

ich habe ja schon gesagt, wo noch eine Referenz ist und auch wie du sie entfernen kannst.

herbivore

C
52 Beiträge seit 2010
vor 14 Jahren

Naja, die Referenz in Controls geht zum DockPanel, der verweist auf DockContents, vermutlich über eine Art ChildCollection.

Wenn er die Referenz rausschmeißt, dann ist alles weg. Wenn ich ihn richtig verstanden habe, dann gehts ihm um die DockContents, die disposed werden sollen.

Nichts destotrotz, beim Close() der MainForm sollte alles weg sein.

M
mydani Themenstarter:in
24 Beiträge seit 2009
vor 14 Jahren

Hallo,

genau so ist es - das DockPanel, Teil der mainForm, welches der Container für die DockContents ist, soll erhalten bleiben. Ich möchte nur die einzelnen DockContents erzeugen und wieder freigeben.
Ich habe gehofft dass es durch irgendeine exotische Debugging-Methode vielleicht möglich ist, Referenzen auf ein Objekt zu finden, welches noch im RAM "rumliegt".

Falls ihr die Muse habt würde ich das Projekt mal zur Verfügung stellen - ich hatte eh vor es früher oder später als OpenSource handzuhaben...

Gruß,
Daniel

C
52 Beiträge seit 2010
vor 14 Jahren

Du kannst ja mal den Auszug posten, wo du die Contents erzeugsts und wie du sie an das Panel übergibts, sollten ja nur 2-3 Zeilen sein.
Und bitte auch das Dispose.

H
116 Beiträge seit 2008
vor 14 Jahren

Aufgebaut ist es wie folgt - es gibt eine mainForm, die enthält das DockPanel.
Dann erzeuge ich 1 bis viele DockContents (die alle von Form erben) - diese lassen sich dann ans DockPanel andocken. Anschließend rufe ich .dispose() der DockContents auf.

Die 1 bis vielen Forms erben hoffentlich von DockContent und nicht von Form direkt. Und in dem jeweiligen Fenster ist dann auch die Eigenschaft HideOnClose auf false gesetzt, nehme ich an. Außerdem weiß das Fenster auch, dass es zu einem DockPanel gehört?


public partial class PanelForm : WeifenLuo.WinFormsUI.Docking.DockContent
{
    // ...
}

public partial class Form1 : Form
{
    // ... hat irgendwo DockPanel dockPanel1

    void openPanelForm()
    {
        var form = new PanelForm(this.dockPanel1);
        form.HideOnClose = false;
        // andere Einstellungen
        form.Show();
    }
}

Dann sollte ein Close() im Unterfenster auch die Resourcen freigeben, es sei denn, Du hast sie noch irgendwo anders zwischengespeichert.

Hinrich

M
mydani Themenstarter:in
24 Beiträge seit 2009
vor 14 Jahren

Hallo,

die Forms sind vom Typ DockContent, deren Eigenschaft HideOnClose ist auf false gesetzt (im Designer). Beim Docken wird ein DockTo(mainPanel) ausgeführt, also weiß es, dass es zum DockPanel gehört.

Ich habe ein kleines einfaches Beispiel gemacht und angehängt.
Im Beispiel werden 5 Windows erzeugt und gedockt, wobei jedes Windows 100MB Daten enthält (als byte[]). Außerdem rufe ich per Timer alle Sekunde den Garbage Collector auf.

Man sieht, dass der Speicher nach dem Schließen aller Fenster noch belegt bleibt.

Gruß,
Daniel

C
52 Beiträge seit 2010
vor 14 Jahren

Hab mal kurz in den Quellcode geguckt. Beim Hinzufügen der einzelnen Contents zum Panel werden WindowsHooks gesetzt, die aber erst beim Disposen des DockPanels wieder aufgehoben werden. (Falls ich das alles richtig gesehen habe), Das würde die "unsichtbaren Referenzen" erklären.