2011-10-11 72 views
1

我在下面提到的代碼中遇到了一個奇怪的問題。我不明白什麼是確切的問題。下面的代碼是Windows服務的一部分。此代碼正在調用一個com類函數在固定時間間隔後對消息隊列執行一些操作。 我爲此使用了System.threading.timer。開始後,服務在一段時間內工作正常,但一段時間後停止工作。Windows服務中的定時器和異常處理

using System; 
using System.IO; 
using System.ServiceProcess; 
using System.Threading; 
using CareMC.VBWrapper.RCWQueue; 

namespace MSPQueueService 
{ 
    public partial class MSPQueueService : ServiceBase 
    { 
     static System.Threading.Timer timer; 
     const int TIMEOUTVALUE = 5000; 
     private int isBusy = 0; 
     public MSPQueueService() 
     { 
      InitializeComponent(); 
     } 

     protected override void OnStart(string[] args) 
     { 
      try 
      { 
       AppendToLog("ONStart Begin"); 
       //Handle Elapsed event 

       TimerCallback timerDelegate = new TimerCallback(OnElapsedTime); 

       timer = new System.Threading.Timer(timerDelegate, null, TIMEOUTVALUE, TIMEOUTVALUE); 
       //EVENT _objEvent = new EVENT(); 
       //_objEvent.ExecuteMSPQueue(); 
       AppendToLog("ONStart End"); 
      } 
      catch (Exception ex) 
      { 
       string ErrorMessage = ex.Message.ToString(); 
       AppendToLog(ErrorMessage); 
      } 

     } 

     private void OnElapsedTime(object state) 
     { 

      //If the isBusy value is 0 then replace it with 1 and continue otherwise it has already been incremented so we're already running 

      //the handler so skip out 

      if (Interlocked.CompareExchange(ref isBusy, 1, 0) != 0) 
      { 
       AppendToLog("OnElapsedTime is already running. isBusy=" + isBusy.ToString()); 
       return; 
      } 

      try 
      { 

       EVENT _objEvent = new EVENT(); 
       AppendToLog("Before Executing ExecuteMSPQueue function."); 
       _objEvent.ExecuteMSPQueue(); 
       AppendToLog("After Executing ExecuteMSPQueue function."); 
      } 
      catch (Exception ex) 
      { 
       AppendToLog(ex.ToString()); 
      } 
      finally 
      { 
       AppendToLog("Resetting isBusy value to 0="); 
       Interlocked.Exchange(ref isBusy, 0); 
       AppendToLog("Value of isBusy after reset =" + isBusy); 

      }; 

     } 


} 

下面是從代碼

10/11/2011上午04時15分03秒smaple日誌:執行ExecuteMSPQueue功能之前。

10/11/2011 4:15:08 AM:OnElapsedTime已在運行。

10/11/2011 4:15:13 AM:OnElapsedTime已在運行。

10/11/2011 4:15:18 AM:OnElapsedTime已在運行。

10/11/2011 4:15:19 AM:執行ExecuteMSPQueue函數後。

10/11/2011 4:15:28 AM:OnElapsedTime已在運行。

10/11/2011 4:15:33 AM:OnElapsedTime已在運行。

10/11/2011 4:15:38 AM:OnElapsedTime已在運行。

10/11/2011 4:15:43 AM:OnElapsedTime已在運行。

10/11/2011 4:15:48 AM:OnElapsedTime已在運行。

10/11/2011 4:15:53 AM:OnElapsedTime已在運行。

這意味着IsBusy變量的值保持爲1而不是重置爲0。通過查看代碼,它是唯一可能的,如果有異常不被捕獲塊捕獲(這是可能的?)

請幫助我。

+2

我認爲你應該將相當長的代碼縮短到你認爲是錯誤的實際行。否則,在我看來,這是一個「TL; DR」的帖子。 –

回答

1

定時器將觸發前一次運行是否結束。如果OnElapsedTime運行時間超過5秒,則當定時器再次執行時,該值仍然爲1。

回調委託從線程池線程中調用,所以這種情況是可能的。

從MSDN:

回調指定要折返,因爲它是 呼籲線程池線程的方法。如果定時器間隔小於執行該方法所需的時間的 ,或者所有線程池線程正在使用且該方法多次排隊,則可以在兩個線程池線程上同時執行該方法 。

編輯:

%的評論,鑑於你的最後塊從不跑步,我猜你的線程登錄「執行後」仍掛或僵持不下,無論是在日誌記錄方法,或者EVENT的終結器(如果有的話)。這是一個調試程序,可能會非常有啓發性。

+0

目前正在發生這種情況,OnElapsedTime在完成上次運行之前會多次觸發。這就是爲什麼我要檢查IsBusy變量的值。但是如果你看看日誌10/11/2011 4:15:19 AM:執行ExecuteMSPQueue函數之後。我期望IsBusy變量的值應該重置爲0.哪些情況沒有發生。 – Sachin

+0

@Sachin,更新了我的帖子 – Joe

0

當心您的日誌記錄方法,您可能遇到併發問題,這可能會導致您遇到的問題。根據您的要求,我會使用Thread + Thread.Sleep()重新設計您的服務。

+0

好點,日誌記錄可能會導致問題here.Let我更改我的日誌記錄代碼,並讓它看看它是否工作 – Sachin