Speicherlöcher?



  • Wie aus dem Post weiter unten zu entnehmen entwickle ich gerade einen Dienst.
    Grundsätzlich gilt natürlich unter DotNet, dass dier Speicherbereinigung durch den Garbage-Collector bereinigt wird. Dies scheint bei einem Dienst NICHT der Fall zu sein. Mein Dienst frisst Speicher. Bei jedem Timeraufruf wird der belegte Speicher mehr.
    Jetzt meine Frage an Euch: Was muss ich freigeben? und vor allem wie?
    Ich vermute mal es muss im Codeblock CatchProcess und GetProcessOwner irgendwas faul sein.
    Ich stellle mal den gesamten Code hier rein

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Diagnostics;
    using System.ServiceProcess;
    using System.Text;
    using System.Threading;
    using System.Configuration.Install;
    using System.Security.Principal;
    using System.Management;
    
    namespace ProcessWatchService
    {
        [RunInstaller(true)]
        public class CronInstaller : Installer
        {
            private ServiceProcessInstaller processInstaller;
            private ServiceInstaller serviceInstaller;
    
            public CronInstaller()
            {
                processInstaller = new ServiceProcessInstaller();
                serviceInstaller = new ServiceInstaller();
    
                processInstaller.Account = ServiceAccount.LocalSystem;
                serviceInstaller.StartType = ServiceStartMode.Manual;
                serviceInstaller.ServiceName = "ServicePW";
    
                Installers.Add(serviceInstaller);
                Installers.Add(processInstaller);
            }
        }
        public class ServicePW : System.ServiceProcess.ServiceBase
        {
            private CronJob job;
            private Timer stateTimer;
            private TimerCallback timerDelegate;
    
            public ServicePW()
            {
                InitializeComponent();
            }
    
            static void Main()
            {
                System.ServiceProcess.ServiceBase[] ServicesToRun;
                ServicesToRun = new System.ServiceProcess.ServiceBase[] { new ServicePW() };
                System.ServiceProcess.ServiceBase.Run(ServicesToRun);
            }
    
            private void InitializeComponent()
            {
            }
    
            protected override void OnStart(string[] args)
            {
                job = new CronJob();
                timerDelegate = new TimerCallback(job.CatchProcess);
                stateTimer = new Timer(timerDelegate, null, 1000, 2000);
    
            }
    
            protected override void OnStop()
            {
                stateTimer.Dispose();
    
            }
        }
    
    // Aufruf alle 4 Sekunden. Ich vermute hier passieren die Speicherlöcher
    
        public class CronJob
        {
            public void CatchProcess(object stateObject)
            {
                Process[] myProcesses = Process.GetProcesses();
                bool killApp = false;
                foreach (Process p in myProcesses)
                {
                    if (p.ProcessName.ToUpper() == "EXPLORER")
                    {
                        killApp =GetProcessOwner(p.Id);
                    }
                }
                if (killApp == true)
                {
                    foreach (Process p in myProcesses)
                    {
                        if (p.ProcessName.ToUpper() == "IEXPLORE")
                        {
                            p.Kill();
                        }
                    }
                }
    
            }
            public bool GetProcessOwner(int pID)
            {
                string query = "Select * From Win32_Process Where ProcessID = " + pID;
                ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
                ManagementObjectCollection processList = searcher.Get();
                string resString = "";
                foreach (ManagementObject obj in processList)
                {
                    string[] argList = new string[] { string.Empty, string.Empty };
                    int returnVal = Convert.ToInt32(obj.InvokeMethod("GetOwner", argList));
                    if (returnVal == 0)
                    {
                        // return DOMAIN\user
                        resString = argList[0];
                        if (resString == "Gast")
                            return true;
                    }
                }
                return false;
            }
        }
    
    }
    


  • Dies scheint bei einem Dienst NICHT der Fall zu sein. Mein Dienst frisst Speicher. Bei jedem Timeraufruf wird der belegte Speicher mehr.

    Auch bei einem Dienst (der unter der CLR läuft) ist der GC aktiv.

    Simon

    Edit:
    Memory Leaks unter .NET enstehen durch Referenzen die Länger (z.B. immer) als benötigt erhalten bleiben. Dies kann z.B. duch eine Event Subscription passieren.
    Um solche Memory Leaks aufzuspüren gibt es Tools.
    http://www.microsoft.com/DOWNLOADS/details.aspx?FamilyID=28bd5941-c458-46f1-b24d-f60151d875a3&displaylang=en

    http://www.codeproject.com/KB/dotnet/Memory_Leak_Detection.aspx

    Edit2:
    BTW: Klassen die IDisposable oder eine Close(..) Methode impl. sollten aufgerufen werden, wenn die entsprechenden Objekte nicht mehr gebraucht werden.

    Zusätzlich kann noch gesagt werden, dass der Speicherverbraucht wachsen wird über eine bestimmte Zeit und dann (irgendwann) der GC wieder aktiv ist und die objekte aufräumt (in mehreren Phasen) und so weiter... ich will damit sagen, Du kannst nicht darauf gehen, dass z.B. ein Objekt angelegt wird, und wenns nicht mehr gebraucht wird sofort wieder freigegeben wird. Wichtig ist, dass der Speicherverbraucht über längere Zeit stabil bleibt (wenn er denn das muss..).



  • Besten Dank für die Hilfe. Tatsächlich dauert es eine Weile bis die Aufräumarbeiten beginnen und dannfällt tatsächlich die Speicherbelegung so um die 3k. Der Eindruck bleibt aber, das Teil frisst Speicher. Es geht nie so weit runter wie einen Lauf davor (Beobachtungszeitraum so um die 15 minuten)

    Das Diagnosetool habe ich runter geladen, gebe aber zu, ich blick da nicht durch was mir das Teil sagen will.

    trotzdem noch mal Danke.



  • Hier noch ein Bericht aus dem MSDN Magazin zum Thema:
    http://msdn.microsoft.com/en-us/magazine/cc163491.aspx


Anmelden zum Antworten