我用C#编写了一个程序,作为Windows服务运行。 应用程序启动并运行正常,但是当我使用pipe理控制台停止服务时,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(); }
该日志消息永远不会写入日志文件。
任何帮助,将不胜感激。 我甚至不知道从哪里开始寻找。 谢谢。
编辑我解决了locking后台线程的问题。 我也注意到了日志声明,所以我知道日志声明不会引起问题。
除了布尔标志之外,我还添加了一个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()函数(这是它自己的线程)while(!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); }
我认为这应该从数据库中读取,排队它find的所有线程,然后等待所有线程完成处理(eventX重置事件)或ShutdownX事件。
一旦ShutdownX事件被触发,外部循环不应该继续,因为closures布尔是真的,然后线程closures它的SQL连接,应该终止。 没有发生这种情况。 有任何想法吗?
您正在使用ThreadPool
。 据报道, 直到线程池中的所有任务完成, OnStop
被调用。 另见这里和这里 。 但是,我认为这不是主要或唯一的原因,因为有些人似乎正在成功地使用它 。
在我看来,你的问题目前说, OnStop
永远不会被调用,但你已经看到它发出的日志消息。 所以我认为, OnStop
确实被调用,但是一些线程并没有注意到这一点。
请使用单个全局对象将所有获取或设置shutdown
代码封装在lock
语句中。 这不是为了原子性或相互排斥。 这是为了确保多处理器系统上正确的内存限制。