C# Minuterie ou d'un Thread.Dormir

j'exécute un service windows et j'utilise une boucle et un Thread.Dormir pour répéter une tâche, serait-il préférable d'utiliser une méthode de minuterie?

Si oui un exemple de code serait formidable

j'utilise actuellement ce code pour répéter

int curMinute;
int lastMinute = DateTime.Now.AddMinutes(-1).Minute;

while (condition)
{
   curMinute = DateTime.Now.Minute;

   if (lastMinute < curMinute) {
         // do your once-per-minute code here
         lastMinute = curMinute;
   }

   Thread.Sleep(50000);      // sleeps for 50 seconds

   if (error condition that would break you out of this) {
       break;      // leaves looping structure
   }
}
44
demandé sur Doug Porter 2009-07-07 15:05:57

11 réponses

class Program
{
    static void Main(string[] args)
    {
        Timer timer = new Timer(new TimerCallback(TimeCallBack),null,1000,50000);
        Console.Read();
        timer.Dispose();
    }

    public static void TimeCallBack(object o)
    {
      curMinute = DateTime.Now.Minute;
      if (lastMinute < curMinute) {
       // do your once-per-minute code here
       lastMinute = curMinute;
    }
}

le code pourrait ressembler à quelque chose comme celui ci-dessus

31
répondu Prashanth 2011-04-08 19:56:06

une minuterie est une meilleure idée, IMO. De cette façon, si on demande à votre service de s'arrêter, il peut répondre à cela très rapidement, et tout simplement ne pas appeler le gestionnaire de temps de nouveau... si vous dormez, le directeur de service devra soit attendre 50 secondes ou tuer votre fil, ni l'un ni l'autre n'est terriblement gentil.

43
répondu Jon Skeet 2009-07-07 11:10:48

il est important de comprendre que votre code dormira pendant 50 secondes entre la fin d'une boucle et le début de la suivante...

une minuterie appellera votre boucle toutes les 50 secondes, ce qui n'est pas exactement la même chose.

ils sont tous les deux valables, mais un minuteur est probablement ce que vous cherchez ici.

11
répondu Christopher Karper 2009-07-07 11:08:26

attention qu'appeler Sleep() va geler le service, donc si le service est demandé d'arrêter, il ne va pas réagir pour la durée de L'appel Sleep ().

7
répondu Philippe Leybaert 2009-07-07 11:14:18

Oui, l'utilisation d'une minuterie libérera un fil qui passe actuellement la plupart de son temps de sommeil. Une minuterie sera également plus précisément allumée chaque minute de sorte que vous n'aurez probablement plus besoin de garder la trace de lastMinute plus.

4
répondu Jon Norton 2009-07-07 11:10:46

pas tout à fait répondre à la question, mais plutôt que d'avoir

   if (error condition that would break you out of this) {
       break;      // leaves looping structure
   }

Vous devriez probablement avoir

while(!error condition)

et je dirais aussi Timer .

2
répondu cjk 2014-09-01 12:05:41

j'ai utilisé des minuteries et du fil.Sommeil (x), ou l'un ou l'autre, selon la situation.

si j'ai un petit morceau de code qui doit fonctionner à répétition, j'utilise probablement une minuterie.

si j'ai un morceau de code qui pourrait prendre plus de temps à exécuter que le temporisateur de retard (comme extraire des fichiers d'un serveur distant via FTP, où je ne contrôle pas ou ne sais pas le retard de réseau ou les tailles de fichier / count), je vais attendre une période fixe de temps entre les cycles.

les deux sont valables, mais comme nous l'avons déjà souligné, ils font des choses différentes. La minuterie exécute votre code toutes les x millisecondes, même si l'instance précédente n'est pas terminée. fil.Sleep (x) attend pendant une période de temps après avoir terminé chaque itération, de sorte que le délai total par boucle sera toujours plus long (peut-être pas beaucoup) que la période de sommeil.

1
répondu jwhitley 2012-07-21 07:57:17

j'ai eu besoin d'un fil pour tirer une fois par minute ( voir la question ici ) et j'ai maintenant utilisé un DispatchTimer basé sur les réponses que j'ai reçues.

les réponses fournissent quelques références que vous pourriez trouver utiles.

1
répondu Simon Temlett 2017-05-23 12:13:35

je suis aussi d'accord, à l'aide d'une minuterie est la meilleure option. J'ai essayé une solution similaire à la vôtre dans le passé et j'ai commencé à avoir des problèmes où la boucle se raterait, et je devrais attendre un autre fil.Sleep() avant de le feu encore une fois. En outre, il a causé toutes sortes de problèmes avec l'arrêt du service, je recevais des erreurs constantes sur la façon dont il ne répondait pas et a dû être fermé.

le code de @Prashanth devrait être exactement ce dont vous avez besoin.

0
répondu Nick DeMayo 2009-07-07 11:37:27

vous pouvez utiliser l'un ou l'autre. Mais je pense que Sleep() est facile, clair et plus court à mettre en œuvre.

0
répondu Umair Ahmed 2014-09-01 12:04:43

je dois dire qu'un sommeil est une meilleure implémentation avec une machine d'état derrière elle. Cela vous permettrait de garder le contrôle de l'application en tout temps, tout en permettant toute réponse nécessaire à un moment précis. Cela permettra également de gérer les callbacks timer qui sont plus courts que le "Processing execution time in the loop "

par exemple..

<!-- language: c# -->
public enum State
{
    Idle = 0,
    Processing = 1,
    Stop = 100,
}
public void Run()
{
    State state = State.Idle;   // could be a member variable, so a service could stop this too

    double intervalInSeconds = 60;
    System.DateTime nextExecution = System.DateTime.Now.AddSeconds(intervalInSeconds);
    while (state != State.Stop)
    {
        switch (state)
        {
            case State.Idle:
                {
                    if (nextExecution > System.DateTime.Now)
                    {
                        state = State.Processing;
                    }
                }
                break;
            case State.Processing:
                {
                    // do your once-per-minute code here

                    // if you want it to stop, just set it state to stop.
                    // if this was a service, you could stop execution by setting state to stop, also
                    // only time it would not stop is if it was waiting for the process to finish, which you can handle in other ways

                    state = State.Idle;
                    nextExecution = System.DateTime.Now.AddSeconds(intervalInSeconds);
                }
                break;
            default:
                break;
        }

        System.Threading.Thread.Sleep(1);
    }
}
-1
répondu Cr4t3r 2013-01-30 17:05:39