2010-08-13 4 views
7

J'ai un service qui frappe une base de données toutes les 10 sec et obtient les données s'il y en a. Le fait est que le traitement de ces données peut prendre jusqu'à 30 secondes. Si j'utilise un minuteur avec un intervalle de 10 secondes, le service recevra deux fois les mêmes données.Temporisateur C# vs thread en service

L'effet d'essayer je suis d'atteindre (juste pour la visualisation):

while(true) 
{ 
    if(Getnrofrows() > 0) 
     do stuff 
    else 
     sleep for 10 sec 
} 

Ppl dire Thread.Sleep est une mauvaise idée dans les services de production, comment dois-je faire cela avec des minuteries?

/micro

+4

Sont-ils aussi en train de dire * pourquoi * Thread.Sleep est une mauvaise idée? – Heinzi

Répondre

10

Avez-vous essayez de définir la réinitialisation automatique de la propriété minuterie false, et permettre à nouveau la minuterie lorsque le processus de données bouffée d'air frais sur

using System; 

public class PortChat 
{ 
    public static System.Timers.Timer _timer; 
    public static void Main() 
    { 

     _timer = new System.Timers.Timer(); 
     _timer.AutoReset = false; 
     _timer.Interval = 100; 
     _timer.Elapsed += new System.Timers.ElapsedEventHandler(_timer_Elapsed); 
     _timer.Enabled = true; 
     Console.ReadKey(); 
    } 

    static void _timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 
    { 
     //Do database refresh 
     _timer.Enabled = true; 
    } 
} 
+0

Exactement ce que je cherchais. THX! –

+0

Désolé, mais ne devrait-il pas être _timer.Enabled = false dans l'événement écoulé? Pourquoi est-il réglé à nouveau à nouveau si c'est fait en main? – Neale

+0

@Neale, La question initiale était de suspendre la boucle jusqu'à ce que quelque chose ne soit pas fini. Quand nous mettons _timer.Autoreset = false alors la boucle ne se produira qu'une seule fois après l'activation de la minuterie. Donc, quand notre boucle se termine avec la lecture, nous activerons de nouveau le minuteur en l'activant – adopilot

0

Il n'y a rien de mal avec cette approche. Un thread dormant ne consomme aucun cycle CPU.

Si vous devez faire quelque chose exactement toutes les X secondes, une minuterie est la voie à suivre. Si, d'autre part, vous voulez faire une pause de X secondes, alors Thread.Sleep est approprié.

+0

Un thread qui dort ne consommera pas de cycles de CPU mais il consommera de nombreuses ressources du noyau en comparaison avec l'objet Timer – Zuuum

1

Je ne vois aucun problème avec l'utilisation de Sleep à tous les autres que vous pourriez finir avec un code moche.

Pour répondre à votre question:

public class MyTest 
{ 
    System.Threading.Timer _timer; 


    public MyTest() 
    { 
     _timer = new Timer(WorkMethod, 15000, 15000); 
    } 


    public void WorkMethod() 
    { 
     _timer.Change(Timeout.Infinite, Timeout.Infinite); // suspend timer 

     // do work 

     _timer.Change(15000, 15000); //resume 

    } 
} 
0

Thread.Sleep est pas mal en soi dans un service, tout ce que vous devez répondre aux commandes de service, de sorte que votre thread de travail ne devrait pas aller dormir pendant une heure, mais a plutôt besoin de dormir pendant de courtes périodes, puis de se réveiller et d'écouter si la partie du contrôleur de service lui dit de s'arrêter pour une raison quelconque.

Vous voulez que si l'administrateur dit à votre service d'arrêter, il s'arrêtera assez vite pour qu'il ne reçoive pas de messages de délai d'attente lorsque l'administrateur ne peut pas être sûr que votre service est arrêté et il est sûr de redémarrer la machine ou similaire.