未调用Windows Service OnStop()

时间:2012-05-17 20:43:16

标签: c# windows service

我在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();
    }

该日志消息永远不会写入日志文件。

任何帮助将不胜感激。我甚至不知道从哪里开始寻找。感谢。

修改 我解决了锁定后台线程的问题。我还注释掉了日志语句,所以我知道日志语句没有引起问题。

除了boolean标志之外,我还添加了一个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()函数(这是它自己的线程)      而(!关机)                 {

                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重置事件)或ShutdownX事件。

一旦触发ShutdownX事件,外部循环不应该继续,因为shutdown bool为true,然后线程关闭它的SQL连接并应该终止。这些都不会发生。有什么想法吗?

1 个答案:

答案 0 :(得分:3)

您正在使用ThreadPool。据报道,OnStop从未被称为until all tasks in the thread pool complete。另请参阅herehere。但是,我倾向于这不是某些人的主要或唯一原因seem to be using it with success

在我看来,您的问题目前表示OnStop永远不会被调用,但您已经看到它发出的日志消息。所以我假设OnStop被调用,但有些线程没有注意到。

请使用单个全局对象包装在shutdown语句中获取或设置lock的所有代码。这不是原子性或互斥性。这是为了确保多处理器系统上存在适当的内存障碍。