3

目前,我正在用 C# 开发一系列 Windows 服务,它们使用计时器 (from System.Timers) 来轮询它们正在运行的机器并将统计信息报告给远程侦听器(远程机器托管 WCF 数据服务)。

设置如下:我有一个用附加功能包装 System.Timers.Timer 的类,它接受一个通用事件处理程序,当计时器经过并记录信息时被触发:

public class GenericPoller
{
    private EventLog _log;
    private string _componentName;
    private System.Timers.Timer _timer;

    public GenericPoller
        (
            double interval, 
            System.Timers.ElapsedEventHandler handler, 
            EventLog log,
            string componentName
        )
    {
        _componentName = componentName;
        _log = log;

        _timer = new System.Timers.Timer();
        _timer.Interval = interval;
        _timer.AutoReset = true;
        _timer.Enabled = false;
        _timer.Elapsed += handler;
    }

    public void StartPolling()
    {
        try
        {
            _timer.Enabled = true;
            _log.WriteEntry
            (
                "Timer started for component '" + _componentName
                + "', with " + _timer.Interval + "ms interval."
            );
        }
        catch
        {
            _log.WriteEntry("Failed to start timer for component '" + _componentName + "'.");
        }
    }

    public void StopPolling()
    {
        try
        {
            _timer.Enabled = false;
            _log.WriteEntry("Timer stopped for component '" + _componentName + "'.");
        }
        catch
        {
            _log.WriteEntry("Failed to stop timer for component '" + _componentName + "'.");
        }
    }

}

我正在实现的任何一个服务都会GenericPoller在它们的构造函数中创建一个,并且在OnStart我通过一个单独的线程调用的方法中StartPolling,以尽可能少地在这个方法中消耗时间。服务类大致如下所示:

public partial class CPUMonitor : ServiceBase
{
    private GenericPoller _poller;
    Thread _thread;

    public CPUMonitor()
    {
        InitializeComponent();

        _poller = new GenericPoller
        (
            HardwareMonitorCommon.Instance.DefaultPollingInterval,
            PollCPU,
            EventLog,
            "CPUMonitor"
        );
    }

    protected override void OnStart(string[] args)
    {
        _thread = new Thread(new ThreadStart(_poller.StartPolling));
        _thread.Start();
    }

    protected override void OnStop()
    {
        _poller.StopPolling();
        _thread.Join();
    }

    private void PollCPU(object sender, System.Timers.ElapsedEventArgs e)
    {

            Code to aqcuire CPU stats and report to WCF data service...
    }
}

我使用installutil.exe命令安装服务。服务有时会在分配的时间内无法启动(错误 1053),但似乎没有任何模式可以解决这个问题。10 次尝试中大约有 4 次尝试失败。

我简直无法理解为什么会发生这种情况。系统/应用程序事件日志没有报告服务进程的任何错误或异常,如果所有“繁重的工作”都发生在单独的线程中,我无法弄清楚为什么会发生超时。

我绝不是编写多线程代码的专业人士/专家,所以我完全期望做错事......我只是看不出它是什么......


编辑:Main方法保留在自动生成的Program.cs文件中,我只修改它以添加将运行的组件:

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    static void Main()
    {
        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[] 
        { 
            new CPUMonitor(),
            new MemoryMonitor()
        };
        ServiceBase.Run(ServicesToRun);
    }
}
4

0 回答 0