C# Windows服务有时会赢得';t启动(电气特性)

C# Windows服务有时会赢得';t启动(电气特性),c#,multithreading,service,timer,windows-services,C#,Multithreading,Service,Timer,Windows Services,目前,我正在C#中开发一系列Windows服务,这些服务使用计时器(来自System.Timers)轮询正在运行的机器,并向远程侦听器报告统计数据(远程机器承载WCF数据服务) 设置如下:我有一个类,它使用附加功能包装System.Timers.Timer,接受在计时器过期时触发的通用事件处理程序和日志信息: public class GenericPoller { private EventLog _log; private string _componentName;

目前,我正在C#中开发一系列Windows服务,这些服务使用计时器(来自
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次

我就是不明白为什么会这样。系统/应用程序事件日志不会报告服务进程中的任何错误或异常,我也不明白如果所有的“繁重工作”都在一个单独的线程中进行,为什么会出现超时

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


EDIT:自动生成的
Program.cs
文件中保留了
Main
方法,我仅对其进行了修改以添加将要运行的组件:

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);
    }
}
静态类程序
{
/// 
///应用程序的主要入口点。
/// 
静态void Main()
{
ServiceBase[]ServicesToRun;
ServicesToRun=新的ServiceBase[]
{ 
新的CPUMonitor(),
新内存监视器()
};
ServiceBase.Run(ServicesToRun);
}
}

伙计,这是一种痛苦。。。。我们有一个在OnStart方法上生成线程的服务,所以它会立即启动,但不知何故,它有时不会启动,并且没有任何错误。。。它无法复制。。。有时我们会收到关于这件事的罚单,我们还远远没有弄明白。@JobaDiniz,是的,我从来没有弄明白过。随着时间的推移,我不再像这样手动设置服务入口点,而是使用TopShelf,它允许您独立运行程序或将其作为Windows服务安装。你也可以试试看!我知道TopShelf但它不能解决问题。。。在幕后,TopShelf仍将以WinService的形式运行我的类…@JobaDiniz,可能不会,但我已经开始使用它,只是为了有一种标准化的方式来设置windows服务,并且只是建议在编写入口点时将其作为一种避免bug的方法。在我自己的例子中,代码确实没有任何明显的错误-我以后也无法重现这个问题。。。