[英]Windows Service OnStop() not called
我已经用C#编写了一个可作为Windows服务运行的程序。 该应用程序启动并运行良好,但是当我使用管理控制台停止该服务时,未调用OnStop函数。
OnStart方法为主程序启动一个后台线程,该后台线程启动另一个线程和一个ThreadPool为其工作。
在OnStop上,我设置了一个布尔标志,所有其他线程都会检查该布尔标志,以查看它们是否应停止处理。 然后所有线程都应完成,并且程序应结束。
这是我的OnStart的代码
protected override void OnStart(string[] args)
{
base.OnStart(args);
mainProgram.IsBackground = true;
mainProgram.Start();
}
该代码有效。 下面是OnStop的代码,据我所知,它永远不会被调用。
protected override void OnStop()
{
Log.LogMessage("Caught shutdown signal from the OS", "debug");
base.OnStop();
shutdown = true;
mainProgram.Join(15000);
if (mainProgram.IsAlive) mainProgram.Abort();
}
该日志消息永远不会写入日志文件。
任何帮助,将不胜感激。 我什至不知道从哪里开始寻找。 谢谢。
编辑我解决了锁定后台线程的问题。 我还注释掉了该日志记录语句,因此我知道该日志语句不会引起问题。
除了布尔标志外,我还添加了ManualResetEvent。 现在,OnStop如下所示:
protected override void OnStop()
{
System.Diagnostics.Debugger.Break();
//Log.LogMessage("Caught shutdown signal from the OS", "debug");
base.OnStop();
shutdown = true;
ShutdownX.Set(); //this is the ManualResetEvent
mainProgram.Join(15000);
if (mainProgram.IsAlive) mainProgram.Abort();
}
应该停止代码的位置在mainProgram.RunAgent()函数(这是它自己的线程)中,而(!shutdown){
SqlCommand DbCommand = dbConnection.CreateCommand();
DbCommand.CommandText = "SELECT id, SourceID, CastingSN, Result FROM db_owner.queue";
SqlDataReader DbReader = null;
try
{
DbReader = DbCommand.ExecuteReader();
while (DbReader.Read() && !shutdown)
{
long SourceID = DbReader.GetInt64(1);
string CastingSN = DbReader.GetString(2);
bool Result = DbReader.GetBoolean(3);
WaitCallback callback = new WaitCallback(oComm.RunAgent);
CommunicatorState commstate = new CommunicatorState(CastingSN, Result, SourceID);
ThreadPool.QueueUserWorkItem(callback, commstate);
callback = null;
commstate = null;
}
//Console.WriteLine("Finished Queueing Threads");
}
catch (SqlException Ex)
{
Log.LogMessage("There was an error with a query run on the FlexNet Database.", "error");
Log.LogMessage(">> " + Ex.Message, "error");
}
finally
{
if (DbReader != null) DbReader.Dispose();
DbCommand.Dispose();
}
ManualResetEvent[] handles = new ManualResetEvent[2] { eventX, ShutdownX };
WaitHandle.WaitAny(handles);
//eventX.WaitOne(Timeout.Infinite, true);
}
我认为这应该从数据库中读取,将找到的所有线程排入队列,然后等待所有线程完成处理(eventX reset事件)或ShutdownX事件。
触发ShutdownX事件后,外部循环不应继续,因为shutdown bool为true,然后线程将关闭其SQL连接并应终止。 这些都没有发生。 有任何想法吗?
您正在使用ThreadPool
。 据报道, 直到线程池中的所有任务完成后才调用OnStop
。 另请参阅此处和此处 。 但是,我倾向于这不是主要或唯一的原因,因为有些人似乎已经成功地使用了它 。
在我看来,您的问题当前表明OnStop
从未被调用,但是您已经看到了它发出的日志消息。 因此,我假设确实调用了OnStop
,但是某些线程没有注意到这一点。
请使用单个全局对象将所有获取或设置为shutdown
代码包装在lock
语句中。 这不是为了原子性或相互排斥。 这是为了确保多处理器系统上有适当的内存屏障。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.