简体   繁体   English

Windows Service OnStop()未调用

[英]Windows Service OnStop() not called

I've written a program in C# that runs as a Windows Service. 我已经用C#编写了一个可作为Windows服务运行的程序。 The application starts up and runs fine, but the OnStop function doesn't get called when I use the Management Console to stop the service. 该应用程序启动并运行良好,但是当我使用管理控制台停止该服务时,未调用OnStop函数。

The OnStart method starts a background thread for the main program, and that background thread starts another thread and a ThreadPool to do work for it. OnStart方法为主程序启动一个后台线程,该后台线程启动另一个线程和一个ThreadPool为其工作。

OnStop I set a boolean flag that all the other threads check in order to see if they should stop processing. 在OnStop上,我设置了一个布尔标志,所有其他线程都会检查该布尔标志,以查看它们是否应停止处理。 The threads should all then finish, and the program should end. 然后所有线程都应完成,并且程序应结束。

Here's the code for my OnStart 这是我的OnStart的代码

protected override void OnStart(string[] args)
    {
        base.OnStart(args);
        mainProgram.IsBackground = true;
        mainProgram.Start();
    }

That code works. 该代码有效。 Below is the code for OnStop, which as far as I can tell doesn't ever get called. 下面是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();
    }

That log message never gets written to the log file. 该日志消息永远不会写入日志文件。

Any help would be appreciated. 任何帮助,将不胜感激。 I don't even know where to start looking. 我什至不知道从哪里开始寻找。 Thanks. 谢谢。

EDIT I solved the problem that was locking the background thread. 编辑我解决了锁定后台线程的问题。 I also commented out that logging statement, so I know the log statement isn't causing the problem. 我还注释掉了该日志记录语句,因此我知道该日志语句不会引起问题。

I added a ManualResetEvent in addition to the boolean flag. 除了布尔标志外,我还添加了ManualResetEvent。 The OnStop now looks like this: 现在,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();
    }

The place this should stop the code is here in the mainProgram.RunAgent() function (which is its own thread) while (!shutdown) { 应该停止代码的位置在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);
            }

I think this should read from the database, queue up all the threads it finds, then wait for either all the threads to finish processing (the eventX reset event) or the ShutdownX Event. 认为这应该从数据库中读取,将找到的所有线程排入队列,然后等待所有线程完成处理(eventX reset事件)或ShutdownX事件。

Once the ShutdownX event is triggered, the outer loop shouldn't continue because the shutdown bool is true, then the thread closes it's SQL connections and should terminate. 触发ShutdownX事件后,外部循环不应继续,因为shutdown bool为true,然后线程将关闭其SQL连接并应终止。 None of this happens. 这些都没有发生。 Any ideas? 有任何想法吗?

You are using ThreadPool . 您正在使用ThreadPool OnStop is reportedly never called until all tasks in the thread pool complete . 据报道, 直到线程池中的所有任务完成后才调用OnStop See also here and here . 另请参阅此处此处 However, I am leaning towards this not being the main or only cause as some people seem to be using it with success . 但是,我倾向于这不是主要或唯一的原因,因为有些人似乎已经成功地使用了它

It seems to me that your question currently says that OnStop never gets called but that you have seen the log message that it emits. 在我看来,您的问题当前表明OnStop从未被调用,但是您已经看到了它发出的日志消息。 So I assume that OnStop does get called but that some of the threads do not notice that. 因此,我假设确实调用了OnStop ,但是某些线程没有注意到这一点。

Please wrap all code that gets or sets shutdown in a lock statement, using a single global object. 请使用单个全局对象将所有获取或设置为shutdown代码包装在lock语句中。 This is not for atomicity or mutual exclusion. 这不是为了原子性或相互排斥。 This is to ensure proper memory barriers on a multiprocessor system. 这是为了确保多处理器系统上有适当的内存屏障。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM