2010-09-03 55 views
17

我有一個Windows服務應用程序。並通過在主控臺模式下運行來進行調試。System.Threading.Timer不會在一段時間後觸發

這裏http://support.microsoft.com/kb/842793 它寫道,Timers.Timer有一個錯誤,並沒有在Windows服務觸發。和解決方法是使用Threading.Timer 而這篇文章是爲.NET 1.0和1.1

我使用.NET 4,但一段時間後Threading.Timer也不會觸發。那麼,這可能是什麼原因? 您可以提出什麼建議作爲解決方法?

感謝,

問候

編輯:我改變定時器從Threading.Timer到Timers.Timer和它工作沒有任何問題。

+1

我認爲一個很好的方法來加速解決這個問題是發佈計時器初始化和啓動代碼。 – Vokinneberg 2010-09-03 12:50:39

+0

使用任何非託管代碼? – 2010-09-03 13:28:48

+0

我打電話來自原生win32 dll函數,但它是在其他線程 – AFgone 2010-09-04 09:00:37

回答

47

你是否保持對你的計時器的引用,以防止它被垃圾收集?

the docs

只要你使用的是定時器,你 必須保持對它的引用。與 任何管理對象一樣,當有 沒有對它的引用時,定時器會被 垃圾收集。 計時器仍處於活動狀態並不會阻止 被收集。

+0

是的,存在對計時器的引用 – AFgone 2010-09-04 08:59:36

+2

@AFgone:哪裏呢?如何*確定*你是否沒有收集垃圾? – 2010-09-04 09:27:48

+2

+1 - 我愛你Jon Skeet,這讓我瘋狂:) – Tr1stan 2010-12-01 14:05:50

4

變通?

就個人而言,我建議使用RegisterWaitForSingleObject函數,而不是定時器,因爲您正在使用確切的原因。 RegisterWaitForSingleObject註冊一個代理程序,它將在您設置爲定時器的時間間隔內被調用,並且易於實現。您可以在幾小時內啓動並運行測試工具。我在Windows服務中使用這種間隔觸發的方法,它是一種久經考驗的真正穩定的解決方案,適用於我。

請閱讀下面的鏈接,並獲取代碼示例和演練文章中的鏈接。

使用運行Windows服務在.NET中的週期性處理:
http://allen-conway-dotnet.blogspot.com/2009/12/running-periodic-process-in-net-using.html

4

你的計時器對象超出範圍和一定的時間,從燒成停止回調後由垃圾收集器被擦除。

保存對課程成員的引用。

0

使用企業庫進行日誌和循環線程的windows服務的完整示例。刪除logger.write行,如果不使用企業庫

namespace Example.Name.Space 
{ 
public partial class SmsServices : ServiceBase 
{ 
    private static String _state = "";   
    private ManualResetEvent _stop = new ManualResetEvent(false); 
    private static RegisteredWaitHandle _registeredWait; 
    public WindowsServices() 
    { 
     InitializeComponent(); 
    } 

    protected override void OnStart(string[] args) 
    {       
     Logger.Write("Starting service", LoggerCategory.Information);    
     _stop.Reset(); 
     _registeredWait = ThreadPool.RegisterWaitForSingleObject(_stop, 
      PeriodicProcess, null, 5000, false); 

    } 

    protected override void OnStop() 
    {    
     // UpdateTimer.Stop(); 
     _stop.Set(); 
     Logger.Write("Stopping service", LoggerCategory.Information); 
    }   
    private static void PeriodicProcess(object state, bool timedOut) 
    { 

     if (timedOut) 
     { 
      // Periodic processing here 
      Logger.Write("Asserting thread state", LoggerCategory.Debug); 
      lock (_state) 
      { 
       if (_state.Equals("RUNNING")) 
       { 
        Logger.Write("Thread already running", LoggerCategory.Debug); 
        return; 
       } 
       Logger.Write("Starting thread", LoggerCategory.Debug); 
       _state = "RUNNING"; 
      } 
      Logger.Write("Processing all messages", LoggerCategory.Information); 
      //Do something 
      lock (_state) 
      { 
       Logger.Write("Stopping thread", LoggerCategory.Debug); 
       _state = "STOPPED"; 
      } 
     } 
     else 
      // Stop any more events coming along 
      _registeredWait.Unregister(null); 


    } 
    } 
} 
相關問題