System.Diagnostics.EventLog泄漏了内存吗?

时间:2016-12-02 13:46:33

标签: c# memory-leaks

当我运行以下代码时:

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,但很快就会上升并且不会停止。为什么?

1 个答案:

答案 0 :(得分: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;

    }
}