none
ManagementObjectSearcher MemoryLeak (??)

    Frage

  • Hallo,

    mittels folgendem Code hole ich in einem Service alle verfügbaren Shares :

            static public bool getShares(ref List<sShare> result)
            {
                bool retval = true;
                ManagementObjectSearcher searcher = null;
                try
                {
                     searcher = new ManagementObjectSearcher( "root\\CIMV2"
                                                            , "SELECT * FROM Win32_Share"
                                                            );
                    foreach (ManagementObject MO in searcher.Get())
                    {
                        try
                        {
                            if (MO["Type"].ToString() == "0")
                            {
                                sShare share = new sShare();
                                share.Name = MO["Name"].ToString();
                                share.Description = MO["Description"].ToString();
                                share.Path = MO["Path"].ToString();
                                share.Status = MO["Status"].ToString();
                                share.Caption = MO["Caption"].ToString();
                                result.Add(share);
                            }
                        }
                        catch (Exception e)
                        {
                            retval = false;
                        }
                        MO.Dispose();
                    }
                }
                catch (Exception e)
                {
                    retval = false;
                }
    
                try
                {
                    if (searcher != null) searcher.Dispose();
                }
                catch
                {
                }
                return retval;
            }

    Mein Problem: Der Code allokiert ständig Speicher, der nicht wieder freigegeben wird. So kommen in ca. 5 Minuten 10MB (!) zusammen, wenn der Code alle 5 Sekunden aufgerufen wird.

    (Bemerkung : Die Eingangsliste "result" wird vor dem Aufruf gelöscht und ist leer.)

    Hat jemand eine Idee, was ich falsch mache ? Alle anderen Fehlerquellen habe ich ausgeschaltet. Wenn nur noch diese Methode läuft, und alles andere drum rum auskommentiert ist, steigt der Speicherbedarf des Service kontinuierlich an ...

    (VS2012 Express, .NET4.0, feststellbar unter W7 32bit & 64bit)

    Georg





    • Bearbeitet GoerschN Freitag, 11. Oktober 2013 20:33
    Freitag, 11. Oktober 2013 20:20

Antworten

  • Google weiß halt doch alles - man muss nur richtig Fragen und dann die richtige Antwort öffnen:

    Nach Verwendung von [MTAThread] anstatt [STAThread] besteht das Memory Leak nicht mehr.

            // [STAThread]
            [MTAThread]
            static void Main()
            {

    • Als Antwort markiert GoerschN Samstag, 12. Oktober 2013 13:11
    Samstag, 12. Oktober 2013 13:11

Alle Antworten

  • Hallo,
    spontan habe ich heraus gefunden, das auch die Liste, die die Get-Methode liefert, wieder mittels Dispose freigegeben werden muss.

    In diesem Zusammenhang würde ich auch using-Blöcke nutzen.

                    using (var list = searcher.Get())
                    {
                        foreach (ManagementObject MO in list)
                        {
                            try
                            {

    Der using-Block ruft am Ende immer Dispose auf. Auch wenn eine Exception geworfen wird.

    Unter Umständen muss man auch noch jedes Element in der Liste wieder selbst frei geben. Aber dazu fand ich nichts (Testen wenn Lösung 1 nichts brachte).


    Koopakiller [kuːpakɪllɐ] (Tom Lambert)
    Webseite | Code Beispiele | Facebook | Twitter | Snippets   C# ↔ VB.NET Konverter
    Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.

    Freitag, 11. Oktober 2013 21:11
    Moderator
  • danke für die Hilfe - sowas habe ich gesucht :)

    Nur leider hilft es nicht - das Löschen der einzelnen Elemente hab ich noch nicht ausprobiert.

    Allerdings habe ich folgenden Test gemacht: Separates Projekt, dass im Prinzip nur den Code beinhaltet. VS als Admin gestartet und laufen gelassen -> dummer Weise bleibt dann der Speicher konstant. Auch wenn ich die Release Version des Programms als Admin starte, bleibt der Speicher konstant.

    Es scheint also was im Zusammenhang mit dem Service zu tun haben. Gibt es da was, das der Garbage Collector nicht aufräumt ?

    Samstag, 12. Oktober 2013 10:01
  • So ein Fehlverhalten ist mir auch nicht bekannt.
    Was aber vielleicht eine Abhilfe schafft ist ein manueller Aufruf von GC.Collect.

    GC.Collect();

    MSDN-Artikel: http://msdn.microsoft.com/de-de/library/vstudio/xe0c2357.aspx


    Koopakiller [kuːpakɪllɐ] (Tom Lambert)
    Webseite | Code Beispiele | Facebook | Twitter | Snippets   C# ↔ VB.NET Konverter
    Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.

    Samstag, 12. Oktober 2013 10:29
    Moderator
  • das werde ich mal ausprobieren.

    Ich habe in der Zwischenzeit mal noch ein paar Tests gemacht. Selbst wenn der Thread, der den Code aufruft, beendet wird, wird der Speicher nicht freigegeben. Jetzt wäre für mich eine Lösung, den Code in einen separates Programm auszulagern, dass durch den Service alle 5 Sekunden gestartet wird und nach Ausführung des Codes sich beendet - nur das ist ja aus einem Service heraus auch nicht so trivial.

    Samstag, 12. Oktober 2013 11:20
  • GC.Collect();
    hilft leider auch nicht
    Samstag, 12. Oktober 2013 11:41
  • Google weiß halt doch alles - man muss nur richtig Fragen und dann die richtige Antwort öffnen:

    Nach Verwendung von [MTAThread] anstatt [STAThread] besteht das Memory Leak nicht mehr.

            // [STAThread]
            [MTAThread]
            static void Main()
            {

    • Als Antwort markiert GoerschN Samstag, 12. Oktober 2013 13:11
    Samstag, 12. Oktober 2013 13:11