2016-12-02 101 views
0

當我運行下面的代碼:System.Diagnostics.EventLog是否泄漏內存?

static void Main(string[] args) 
{ 
    if (!System.Diagnostics.EventLog.SourceExists("eventSource")) 
    { 
     System.Diagnostics.EventLog.CreateEventSource("eventSource", ""); 
    } 

    System.Diagnostics.EventLog eventLog = new System.Diagnostics.EventLog();   
    eventLog.Source = "eventSource"; 
    eventLog.Log = ""; 

    for (int i = 0; i < 10000; i++) 
    { 
     Thread.Sleep(100); 

     eventLog.WriteEntry("test", EventLogEntryType.Information); 

     //I also tried the static method, the program still leaks 
     //System.Diagnostics.EventLog.WriteEntry("eventSource", "test", EventLogEntryType.Information); 
    } 

    Console.ReadKey(); 
} 

內存使用量開始1MB左右,但很快就站起來,並不會停止。爲什麼?

+0

你減少你的循環,看看會發生什麼,如果你的程序也適用於readkey? – Sebastian

+1

內存使用量上升的事實並不一定意味着你「泄漏」了內存,只是你使用了很多內存。如果沒有正確處理對象(http://madgeek.com/articles/leaks/leaks.en.html),在完成正在做的事情並繼續前進之後,如果使用情況沒有回落,就會發生內存泄漏。話雖如此,你應該在使用後Dispose()你的EventLog,然後等待一些(未指定數量的)時間,直到GarbageCollector完成它的事情。 – Arie

+0

其實我在windows服務中有這個泄漏,並且只有當我使用EventLog時纔會發生泄漏。上面的代碼是試圖重現泄漏。 @Sebastian有100個循環,內存佔用空間很大。 – gobes

回答

1

我使用與指定的事件日誌安裝Windows服務代碼:

[RunInstaller(true)] 
public partial class SampleServiceInstaller : System.Configuration.Install.Installer 
{ 
    private string SampleServiceName = string.Empty; 
    private string SampleLogName = string.Empty; 

    public SampleServiceInstaller() 
    { 
     this.SampleServiceName = "SampleService"; 
     this.SampleLogName = this.SampleServiceName + "Log"; 

     ServiceProcessInstaller serviceProcessInstaller = new ServiceProcessInstaller(); 
     serviceProcessInstaller.Password = null; 
     serviceProcessInstaller.Username = null; 
     serviceProcessInstaller.Account = ServiceAccount.LocalSystem; 

     ServiceInstaller serviceInstaller = new ServiceInstaller(); 
     //This must be identical to the WindowsService.ServiceBase name 
     // set in the constructor of WindowsService.cs 
     serviceInstaller.ServiceName = this.SampleServiceName; 
     serviceInstaller.DisplayName = this.SampleServiceName; 
     serviceInstaller.StartType = ServiceStartMode.Automatic; 
     serviceInstaller.Description = "Sample Windows Service"; 

     // kill the default event log installer 
     serviceInstaller.Installers.Clear(); 

     // Create Event Source and Event Log     
     // This recreates the log every time the service is reinstaled (old messages are lost) 
     if (EventLog.SourceExists(this.SampleServiceName)) EventLog.DeleteEventSource(this.SampleServiceName); 
     System.Diagnostics.EventLogInstaller logInstaller = new System.Diagnostics.EventLogInstaller(); 
     logInstaller.Source = this.SampleServiceName; // use same as ServiceName 
     logInstaller.Log = this.SampleLogName; //can't be the same as service name 

     // Add all installers 
     this.Installers.AddRange(new Installer[] { 
        serviceProcessInstaller, serviceInstaller, logInstaller 
     }); 

    } 

    public override void Install(System.Collections.IDictionary savedState) 
    { 
     base.Install(savedState); 
    } 
    protected override void OnBeforeUninstall(System.Collections.IDictionary savedState) 
    { 
     base.OnBeforeUninstall(savedState); 
    } 

服務代碼:

public partial class SampleService : ServiceBase 
{ 
    /// <summary> 
    /// Designer variable. 
    /// </summary> 
    private System.ComponentModel.IContainer components = null; 

    /// <summary> 
    /// Event log for the service 
    /// </summary> 
    EventLog serviceLog; 

    /// <summary> 
    /// Public Constructor for WindowsService. 
    /// - Initialization code here. 
    /// </summary> 
    public SampleService() 
    { 
     InitializeComponent(); 
    } 

    /// <summary> 
    /// The Main Thread: list of services to run. 
    /// </summary> 
    static void Main() 
    { 
     ServiceBase[] ServicesToRun; 
     ServicesToRun = new ServiceBase[] { new SampleService() }; 
     ServiceBase.Run(ServicesToRun); 
    } 

    /// <summary> 
    /// Startup code 
    /// </summary> 
    /// <param name="args"></param> 
    protected override void OnStart(string[] args) 
    { 
     base.OnStart(args); 
     // 
     // run your own start code here 
     // 
     serviceLog.WriteEntry("My service started", EventLogEntryType.Information, 0); 
    } 

    /// <summary> 
    /// Stop code 
    /// </summary> 
    protected override void OnStop() 
    { 
     // 
     // run your own stop code here 
     // 
     serviceLog.WriteEntry("My service stopped", EventLogEntryType.Information, 0); 

     base.OnStop(); 
    } 

    /// <summary> 
    /// Cleanup code 
    /// </summary> 
    /// <param name="disposing"></param> 
    protected override void Dispose(bool disposing) 
    { 
     // 
     // do disposing here 
     // 

     if (disposing && (components != null)) 
     { 
      components.Dispose(); 
     } 
     base.Dispose(disposing); 
    } 

    /// <summary> 
    /// Pause code 
    /// </summary> 
    protected override void OnPause() 
    { 
     base.OnPause(); 
     // 
     // code to run if service pauses 
     // 
    } 

    /// <summary> 
    /// Continue code 
    /// </summary> 
    protected override void OnContinue() 
    { 
     base.OnContinue(); 
     // 
     // code tu run when service continues after being paused 
     // 
    } 

    /// <summary> 
    /// Called when the System is shutting down 
    /// - when special handling 
    /// of code that deals with a system shutdown, such 
    /// as saving special data before shutdown is needed. 
    /// </summary> 
    protected override void OnShutdown() 
    { 
     // 
     // code tu run when system is shut down 
     // 
     base.OnShutdown(); 
    } 

    /// <summary> 
    /// If sending a command to the service is needed 
    /// without the need for Remoting or Sockets, 
    /// this method is used to do custom methods. 
    /// int command = 128; //Some Arbitrary number between 128 & 256 
    /// ServiceController sc = new ServiceController("NameOfService"); 
    /// sc.ExecuteCommand(command); 
    /// </summary> 
    /// <param name="command">Arbitrary Integer between 128 & 256</param> 
    protected override void OnCustomCommand(int command) 
    { 
     base.OnCustomCommand(command); 
     // 
     // handle custom code here 
     // 
    } 

    /// <summary> 
    /// Useful for detecting power status changes, 
    /// such as going into Suspend mode or Low Battery for laptops. 
    /// </summary> 
    /// <param name="powerStatus">The Power Broadcast Status 
    /// (BatteryLow, Suspend, etc.)</param> 
    protected override bool OnPowerEvent(PowerBroadcastStatus powerStatus) 
    { 
     // 
     // handle power events here 
     // 
     return base.OnPowerEvent(powerStatus); 
    } 

    /// <summary> 
    /// To handle a change event 
    /// from a Terminal Server session. 
    /// Useful if determining 
    /// when a user logs in remotely or logs off, 
    /// or when someone logs into the console is needed. 
    /// </summary> 
    /// <param name="changeDescription">The Session Change 
    /// Event that occured.</param> 
    protected override void OnSessionChange(SessionChangeDescription changeDescription) 
    { 
     // 
     // handle session change here 
     // 
     base.OnSessionChange(changeDescription); 
    } 

    private void InitializeComponent() 
    { 
     components = new System.ComponentModel.Container(); 
     // first 8 letters should be unique 
     this.ServiceName = "SampleService"; 

     // if you want to log service event to log registered while installing the service 
     string newLogName = this.ServiceName + "Log"; 
     string newSourceName = this.ServiceName; 

     if (!EventLog.SourceExists(newSourceName)) 
     { 
      EventLog.CreateEventSource(newSourceName, newLogName); 
     } 
     serviceLog = new EventLog(); 
     serviceLog.Source = newSourceName; 
     serviceLog.Log = newLogName; 

     // Causes log to be disposed when the service is disposed 
     components.Add(serviceLog); 

     // Flags set whether or not to handle that specific type of event. 
     this.CanHandlePowerEvent = true; 
     this.CanHandleSessionChangeEvent = true; 
     this.CanPauseAndContinue = true; 
     this.CanShutdown = true; 
     this.CanStop = true; 

    } 
} 
+0

雖然如果我不能解釋爲什麼,用你的代碼泄漏幾乎沒有了...仍然有小幅上漲,但沒有什麼比前一個峯值!謝謝 :) – gobes