2010-10-08 5 views
1

J'ai un service Windows qui exécute quatre temporisateurs pour une application de surveillance. Le temporisateur en question ouvre une requête Web, interroge un service Web de repos et enregistre les résultats dans une base de données.Timer dans le service Windows C# de ne pas redémarrer

S'il vous plaît voir la méthode ci-dessous écoulée:

 void iSMSPollTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 
    { 
     iSMSPollTimer.Stop(); 
     try 
     { 
      Logger.Log("iSMSPollTimer elapsed - polling iSMS modem for new messages"); 
      string url = "http://...:../recvmsg?user=" + iSMSUser + "&passwd=" + iSMSPassword; 
      HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); 
      HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 
      Stream resStream = response.GetResponseStream(); 

      XmlSerializer serializer = new XmlSerializer(typeof(Response)); 
      using (XmlReader reader = XmlReader.Create(resStream)) 
      { 
       Response responseXml = (Response)serializer.Deserialize(reader); 
       if (responseXml.MessageNotification != null) 
       { 
        foreach (var messageWrapper in responseXml.MessageNotification) 
        { 
         DataContext dc = new DataContext(); 
         DateTime monitorTimestamp = DateTime.Now; 

         if (messageWrapper.Message.ToUpper().EndsWith("...")) 
         { 
          //Saved to DB 
         } 
         else if (messageWrapper.Message.ToUpper().EndsWith("...")) 
         { 
          //Saved to DB 
         } 
         dc.SubmitChanges(); 
        } 
       } 
       else 
       { 
        Logger.Log("No messages waiting in the iSMS Modem"); 
       } 
      } 
      Logger.Log("iSMSPollTimer processing completed"); 
     } 
     catch (Exception ex) 
     { 
      Logger.Log(GetExceptionLogMessage("iSMSPollTimer_Elapsed", ex)); 
      Logger.Debug(GetExceptionLogMessage("iSMSPollTimer_Elapsed", ex)); 
     } 
     finally 
     { 
      iSMSPollTimer.Start(); 
     } 
    } 

Quand je regarde les messages du journal, je reçois « traitement de iSMSPollTimer terminé » et au hasard après la minuterie ne redémarre pas.

Des pensées?

+0

Tout cela sur un seul fil? –

+0

@Aaron: Peu probable, puisque les minuteurs qui fonctionnent dans les services utilisent tous des threads à exécuter ... –

Répondre

2

Je pense qu'il y a un problème potentiel de réentrance ici, mais je ne peux pas mettre le doigt dessus exactement.

Je dirais que, plutôt que d'appeler Timer.Stop puis Timer.Start, définissez la propriété AutoReset à false de la minuterie lors de sa création. Cela évitera tout problème de réentrance car la minuterie est automatiquement arrêtée la première fois que l'intervalle s'écoule.

Votre code de gestionnaire reste le même sauf que vous supprimez le code qui appelle iSMSPollTimer.Stop. Je ne dis pas que cela résoudra votre problème à coup sûr, mais cela éliminera le doute persistant à propos d'un problème de réentrance.

+0

Merci, je vais essayer. C'est très intermittent. Le délai d'attente de la minuterie est de 1 minute - et peut-être une fois par semaine, elle s'arrêtera tout simplement. Le problème est que c'est un notifiaction de niveau 2 pour nous et cela arrive toujours quand nous sommes profondément endormis! – Adam

+0

L'autre partie étrange est que j'ai quatre autres minuteries toutes configurées de la même manière qui n'ont pas ce problème - et j'ai plusieurs autres services Windows déployés en utilisant cette même méthodologie. Les méthodes que vous suggérez ont des avantages évidents, il est juste étrange que cette instance spécifique ait un problème. – Adam

0

Ce problème est assez bien connu avec l'utilisation de compteurs en service .NET. Les gens vous diront d'utiliser un autre type de minuterie (Threading vs System), mais à la fin, ils vous échoueront aussi. Combien de temps avant qu'ils arrêtent de déclencher? Plus votre intervalle est court, plus vite il échouera. Si vous le réglez à 1 seconde, vous verrez que cela se produit toutes les deux heures.

La seule solution de contournement que j'ai trouvée fonctionnant pour moi, ne dépend pas entièrement des minuteries et utilise une boucle while avec une fonction Sleep à l'intérieur.

Questions connexes