2010-09-03 7 views
17

J'ai une application de service Windows. Et le débogage en exécutant en mode console.System.Threading.Timer ne se déclenche pas après un certain temps

Ici http://support.microsoft.com/kb/842793 il est écrit que Timers.Timer a un bug et ne déclenche pas dans les services Windows. Et solution consiste à utiliser Threading.Timer Et cet article est pour .NET 1.0 et 1.1

J'utilise .NET 4, mais après un certain temps Threading.Timer aussi ne se déclenche pas. Alors, quelle peut être la raison de cela? Et que pouvez-vous suggérer comme une solution de contournement?

Merci,

Cordialement

EDIT: J'ai changé la minuterie de Threading.Timer à Timers.Timer et il fonctionne sans aucun problème.

+1

Je pense qu'un bon moyen d'accélérer la résolution de ce problème consiste à afficher l'initialisation du Timer et le code de démarrage. – Vokinneberg

+0

En utilisant un code non managé? –

+0

J'appelle une fonction de dll win32 natif, mais il est sur un autre thread – AFgone

Répondre

47

Conservez-vous une référence à votre minuterie quelque part pour éviter qu'elle soit collectée?

De the docs:

Tant que vous utilisez une minuterie, vous doit conserver une référence. Comme avec tout objet géré, un temporisateur est soumis à la collecte des ordures lorsqu'il existe aucune référence. Le fait qu'un temporisateur soit toujours actif n'empêche pas que soit collecté.

+0

oui il existe une référence à une minuterie – AFgone

+2

@AFgone: Où? Comment êtes-vous sûr que ce n'est pas de la poubelle? –

+2

+1 - Je t'aime Jon Skeet, ça me rendait fou :) – Tr1stan

4

Solution de contournement?

Personnellement, je suggère d'utiliser une fonction RegisterWaitForSingleObject par opposition à des temporisations pour le exact raison pour laquelle vous rencontrez. Le RegisterWaitForSingleObject inscrit un délégué à appeler sur l'intervalle que vous avez réglé à une minuterie et sont super facile à implémenter. Vous pourriez avoir un harnais de test opérationnel en quelques heures. J'utilise cette méthode de déclenchement d'intervalle dans mes services Windows et c'est une solution stable éprouvée qui fonctionne pour moi.

Lisez le lien ci-dessous et accédez aux liens de l'article pour obtenir des exemples de code et des procédures pas à pas.

Exécution d'un processus périodique dans .NET en utilisant un service Windows:
http://allen-conway-dotnet.blogspot.com/2009/12/running-periodic-process-in-net-using.html

4

Votre objet de minuterie est hors de portée et est effacé par Garbage Collector après un certain temps, ce qui arrête callbacks de tir.

Enregistrer la référence dans un membre de classe.

0

Exemple complet d'un service Windows utilisant la bibliothèque d'entreprise pour la consignation et les threads récurrents. Supprimer les lignes logger.write si vous n'utilisez pas la bibliothèque d'entreprise

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); 


    } 
    } 
}