C# Windows服务有时会赢得';t启动(电气特性)
目前,我正在C#中开发一系列Windows服务,这些服务使用计时器(来自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;
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的方法。在我自己的例子中,代码确实没有任何明显的错误-我以后也无法重现这个问题。。。