使用shutdown事件的Windows服务无法停止服务

时间:2015-07-21 15:33:09

标签: c# windows-services manualresetevent

我已经编写了一个Windows服务,试图从MSMQ读取消息并处理它们。我已经为我的项目添加了一个安装程序,我已将启动设置为手动。我安装该服务,然后通过“服务”工具启动它。然后我可以回到我的项目并附加到该过程以逐步执行代码。

但是,无论我做什么,我都无法在代码或服务工具中停止服务。我只能这样认为,因为我使用ManualResetEvent类来控制服务。这是我的代码。我试图测试错误部分,因为此时它应该抛出错误并停止服务。

在我的服务类中,我有:

private readonly ManualResetEvent _shutdownEvent = new ManualResetEvent(false);
    private Thread _thread;

    public TestService()
    {
        InitializeComponent();
    }

    protected override void OnStart(string[] args)
    {
        _thread = new Thread(WorkerThread)
        {
            Name = "Test Messaging Reader Service Thread",
            IsBackground = true
        };
        _thread.Start();

    }

    protected override void OnStop()
    {
        _shutdownEvent.Set();
        if (!_thread.Join(3000))
        { // give the thread 3 seconds to stop
            _thread.Abort();
        }
        IError logger = new Logger();
        Exception ex = new Exception("The Test Messaging Service has been stopped.");
        logger.Log(this, SeverityEnum.Warning, ex);
    }

    private void WorkerThread()
    {
        try
        {

            while (!_shutdownEvent.WaitOne(0))
            {
                TestMessageQueueReader processQueue = new TestMessageQueueReader();
                processQueue.ReadFromQueue();
                _shutdownEvent.Set();
                _shutdownEvent.Reset();
            }
        }
        catch (Exception)
        {

            _shutdownEvent.Set();
            _shutdownEvent.Close();
        }

    }

当我单步执行代码时,它会按预期落入异常,此时我希望能够停止服务。

1 个答案:

答案 0 :(得分:1)

工作线程在测试之前立即重置事件:

        while (!_shutdownEvent.WaitOne(0))
        {
            // ...
            _shutdownEvent.Reset();
        }

这意味着除非停止请求恰好在恰当的时间进入,否则将被忽略。

相反,循环应如下所示:

        while (!_shutdownEvent.WaitOne(0))
        {
            TestMessageQueueReader processQueue = new TestMessageQueueReader();
            processQueue.ReadFromQueue();
        }

您也不应该从工作线程关闭事件,因为其他线程可能仍然需要它。 (当进程退出时,事件将自动关闭,因此您无需担心。)

对于异常处理,您无法通过设置事件来停止服务。如果有多个工作线程,设置事件将停止它们,但不会停止服务本身。我不完全确定你如何使.NET服务停止,但尝试调用ServiceBase.Stop