2015-07-21 126 views
1

我写了一个Windows服务,试图从MSMQ读取消息并处理它们。我已将一个安装程序添加到我的项目中,并且已将启动设置为手动。我安装该服务,然后通过服务工具启动它。然后,我可以返回到我的项目并附加到该过程以逐步完成代码。使用关机事件不能停止服务的Windows服务

但是,无论我做什么,我都无法在代码或服务工具中停止该服务。我只能认为这是因为我使用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

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

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

这意味着,除非停止要求在正确的时间到来时,它会被忽略。

相反,循环应该是这样的:

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

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

至于异常处理,您不能简单地通过设置事件来停止服务。如果有多个工作线程,设置该事件将会阻止它们,但不是服务本身。我不完全确定你如何使.NET服务本身停止,但请尝试拨打ServiceBase.Stop

+0

在服务的构造函数中,我设置了CanStop = true;这肯定是必需的,以便用户可以从管理控制台停止服务。这一点现在似乎工作。然而,当我走下我的例外路线时,我想强制服务停止,我已经从循环中删除了Reset()事件,并在Catch块中放置了_shutdownEvent.Set(); _shutdownEvent.Close();和_shutdownEvent.Dispose(),但OnStop()事件不会被触发。我甚至试过这个.Stop(),但仍然不会破坏OnStop事件:( – bilpor

+0

好吧,不好,但在OnStop事件中,如果我放置以下2行代码,那么服务真正停止。 ExitCode = 0; Environment.Exit(Environment.ExitCode); – bilpor