2010-10-21 9 views
8

Ich versuche, die Speichernutzung einer WinForm-Anwendung zu reduzieren.Einfach öffnen und schließen Dialog Winform erhöht die Speichernutzung

In der Anwendung gibt es ein Hauptformular und ein Einstellungsformular. Wenn die Schaltfläche "Einstellung" gedrückt wurde, wird das Einstellungsformular als modales Formular angezeigt. Das Einstellungsformular lädt die app.config-Daten aus der Konfigurationsdatei und liest sie als Hashtable in den Speicher. Nachdem das Einstellungsformular geschlossen wurde, wird die Dispose-Methode von Windows.Forms.Form aufgerufen. Die Dispose-Methode ist so einfach wie das Hashtables-Objekt und das app.config-Objekt auf null setzen.

anzeigen SettingForm als modalform:

private void btnSettings_Click(object sender, EventArgs e) 
    { 
     frmConfig form = new frmConfig(); 
     form.StartPosition = FormStartPosition.CenterScreen; 
     //MessageBox.Show(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase)); 
     form.ShowDialog(this); 
     form.Dispose(); 
    } 

Dispose-Methode:

protected override void Dispose(bool disposing) 
    { 
     if (disposing && (components != null)) 
     { 
      components.Dispose(); 
      // Release managed resources 
      Logger.Verbose("Disposing SettingForm"); 
      mySetting = null; 
      testFtp = null; 
     } 
     base.Dispose(disposing); 
    } 

Hinweis: mySetting ist eine Instanz der Klasse mit allen app.config Daten gewesen Last in Hashtable, und testFtp ist ein benutzerdefiniertes Objekt für die FTP-Funktion. Soll ich Dispose-Methode für diese zwei Klassen implementieren und mit

mySetting.Dispose(); 
testFtp.Dispose(); 

, anstatt sie auf null gesetzt, da sie themself/mit nicht verwalteten Ressourcen umgehen?

Aber jedes Mal drücken Sie die Schaltfläche "Einstellung" und schließen Sie die Einstellung Formular erhöht private Byte für ein paar hundert K. Speicherlecks? Wie könnte ich es loswerden?

+1

Es wäre hilfreich, wenn Sie zumindest etwas von Ihrem Code, insbesondere den Code, wo Sie das Formular modal und Ihre vollständige Dispose-Methode aus dem Einstellungsformular angezeigt. – MusiGenesis

+0

Auch ein einfacher Logging- oder debug.print-Aufruf oder was auch immer innerhalb der Dispose-Methode wird bestätigen, ob es tatsächlich jemals aufgerufen wird oder nicht. – MusiGenesis

+1

Wenn Sie den Verweis auf null setzen, wird der Speicher nicht freigegeben. –

Antwort

1

Wie Sie am Ende Ihrer Frage vorgeschlagen haben, würde ich die Implementierung von IDisposable unter mySetting und testFtp empfehlen. Sie sollten besser Bereinigung von Ressourcen sehen, wenn Sie die folgende implementiert haben:

protected override void Dispose(bool disposing) { 
    if (disposing && (components != null)) { 
     components.Dispose(); 

     // Release managed resources 
     Logger.Verbose("Disposing SettingForm"); 
     mySetting.Dispose(); 
     testFtp.Dispose(); 
    } 

    base.Dispose(disposing); 
} 

Kleine edit: Basierend auf Nayan Antwort und die Antwort, die er auf Links: Ich würde die Umsetzung der IDisposable sehr empfehlen. Unter Verwendung Forms und abgeleitet von Forms Klasse Schreien, "Überprüfen Sie für die Notwendigkeit, IDisposable zu implementieren." Dies bedeutet nicht, dass Ihr Code es implementieren sollte, nur dass Sie wirklich überprüfen sollten, um sicherzustellen, dass Sie es nicht brauchen. Für Formulare werden normalerweise viele Ereignisse veröffentlicht und abonniert. Formulare sind auch berüchtigt dafür, ein Sammelbecken für Ressourcen zu werden, IMO.

+0

Vielen Dank, ich denke Memory-Management in .NET sind wirklich nicht so einfach, ein paar offensichtlich Dinge ausschließen. Ich habe so ziemlich alles Notwendige gemacht (IDisposable ganz unten, wo es Sinn macht (unmanaged ressources invloved) und zwei Profiler cross check). Die Speicherauslastung ist jetzt viel stabiler. Aber benutze immer mehr Zeit. Ich meine, wenn ich mich so sehr um Speicher kümmere, sollte ich überlegen, alle GUI-Sachen zu entfernen und darüber nachzudenken, C++ oder C: D zu benutzen –

1

Der Speicher wird möglicherweise wegen eines anderen Codes nicht freigegeben. Da Sie nicht viele Details zur Verfügung gestellt haben, gehe ich davon aus, dass alles andere optimal ist.

Die Objekte, mit denen Sie arbeiten, werden vom Garbage Collector (wie Sie es kennen) gesammelt. Aber sie werden möglicherweise nicht aus der Erinnerung entlassen, wenn Sie es wollen. .NET-Objekte werden besser dem Garbage Collector überlassen.

Wie pro warum der Speicher kann nicht freigegeben werden immer you have the answers here.

Einstellung Objektverweis auf Null nicht viel Unterschied machen. Andererseits habe ich persönlich einige Male aufgenommen, Objekte, die lebendig zurückkommen (und an alte Generationen weitergegeben werden), weil Sie sie verwenden, während Sie null auf dasselbe setzen. Es ist eine andere Form der Interferenz mit GC, aber Ihre Wahl.

Sie müssen möglicherweise IDisposable nicht implementieren, aber wenn Sie mit Streams, Betriebssystem behandelt, nicht verwalteten Ressourcen arbeiten, sollten Sie dann.

Edit:

Der Speicherverbrauch hoch sein kann, aber es ist GC Verantwortung es so lange zu befreien, wie Sie Verweise nicht am Leben erhalten. Also, wenn Sie alle Vorsichtsmaßnahmen getroffen haben, scheint es immer noch, dass Ihre Anwendung viel Speicher verbraucht. Das ist akzeptabel, da das Freigeben der nicht referenzierten Objekte der Verantwortung des Müllsammlers unterliegt.

+0

Nach diesem Artikel fand ich es sehr nützlich für Anfänger wie mich übrigens, http://www.dotnetfunda.com/articles/article625-best-practices-no5-detecting-net-application-memory -leaks-.aspx Konsequenter Anstieg der privaten Byte-Speicher-Nutzung zeigt ein unmanaged Ressourcen-Leck, in diesem Fall muss ich sicherstellen, dass sie ordnungsgemäß freigegeben sind, was bedeutet, ich brauche IDisposable ganz nach unten, denke ich? –

+0

Das ist ein toller Artikel den ich vermisst habe. Dank dafür! Ok, wenn Sie "wissen", dass es nicht gemanagter Speicherverlust ist, dann finden Sie heraus, wo der nicht verwaltete Speicher zugewiesen wird. Sie können die IDisposable-Schnittstelle implementieren und die nicht verwalteten Elemente des Objekts freigeben. Stellen Sie aber auch sicher, dass die Codes, deren Umfang auf eine Funktion beschränkt ist, auch den Speicher freigeben. Sie können nicht in der Dispose-Methode freigegeben werden. Zum Beispiel: Schließen eines Streams in einer Funktion - das kann nur in dieser Funktion gehandhabt werden! Alles Gute! – Nayan

0

Warum denken Sie, es ist ein Leck? GC ist nicht verpflichtet, Speicher sofort freizugeben, unter gewissen Umständen kann er die Sammlung nie wirklich durchführen, und das wäre in Ordnung.

Wenn Sie diese Kilobytes wirklich sofort freigeben müssen, können Sie GC erzwingen, die Bereinigung unmittelbar nach den Veräußerungen durchzuführen, aber es ist im Allgemeinen ein kostspieliger Vorgang und kann die Gesamtleistung beeinträchtigen.

Verwandte Themen