原因是有个quartz job是从启动开始就不会休息的任务,做的事也相对于简单。在维护时,虽然有写了一个bat来卸载服务,xxx.exe uninstall 【topshelf来做services】虽然可以直接卸载服务,但无法把进程正常结束,倒置一直停留并持续运行中。只要手工KILL进程就可以了。

应该说这一直是我余留的老问题,由于有一个简单有效的临时方案,所以一直没有彻底去解决。

Thread.Interrupt

先来看一示例,相对于:

    class Program
    {
        static bool isShutdown = false;
        static void run()
        {
            long secondUnit = 10000 * 1000;
            while (!isShutdown)
            {
                Console.WriteLine("线程运行中……");
                long time = System.DateTime.Now.Ticks;
                while ((System.DateTime.Now.Ticks - time) < secondUnit)
                {
                }
            }
            Console.WriteLine("线程退出。");
        }
        static void Main(string[] args)
        {
            Thread thread = new Thread(new ThreadStart(run));
            Console.WriteLine("启动线程。");
            thread.Start();
            Thread.Sleep(3000);
            Console.WriteLine("执行Interrupt()。");
            thread.Interrupt();
            Thread.Sleep(3000);
            Console.WriteLine("退出程序");
            Console.Read();
        }
    }

以上,执行结果:
启动线程。
线程运行中……
线程运行中……
线程运行中……
执行Interrupt()。
线程运行中……
线程运行中……
线程运行中……
退出程序
线程运行中……
线程运行中……
…..

并没有跟我们想的一般,甚至程序退出后还在运行中。

原因是 Thread.Interrupt 并不会直接中断一个正在运行的线程。MSDN解释道:

如果此线程当前未阻塞在等待、休眠或联接状态中,则下次开始阻塞时它将被中断。
ThreadInterruptedException 在中断的线程中引发,但要在该线程阻塞之后才引发。如果该线程一直未阻塞,则一直都不会引发该异常,因而该线程可能无需中断就能完成。

而正确的中断线程应该是通过共享变量来,即 IsShutdown。所以对于Job而言合理处理IsShutdown非常重要。

WaitToKillServiceTimeout

等待杀死Service时间,换言之对于一个Service被停止时,会有多长时间来等待。如果按我没有合理的处理IsShutdown 来说,设置多长时间也是徒劳。

位置:HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control,默认:5000毫秒。

故而,综合以上两点。

每次正在运行的任务,需要利用中断变量来判断是否正确退出并做一些存储工作,否则会变得很为难。