2016-12-02 1 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). 그런 말로하면 GarbageCollector가 그 일을 할 때까지 사용 후 EventLog를 Dispose() 한 다음 시간의 일부 (지정되지 않은 금액)를 기다려야합니다. – Arie

+0

실제로 Windows 서비스에서이 누수가 있고 누출은 EventLog를 사용할 때만 발생합니다. 위의 코드는 누출을 재현하려는 시도입니다. @Sebastian 100 루프를 사용하면 메모리 사용 공간이 높은 수준으로 유지됩니다. – gobes

답변

1

I가 지정된 이벤트 로그와 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

관련 문제