2015-07-21 80 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