System.Timers.Timer / Threading.Timer vs Thread avec WhileLoop + Thread.Sleep pour les tâches périodiques

Dans mon application, je dois envoyer des battements de cœur périodiques à une application “frère”.

Est-ce mieux accompli avec System.Timers.Timer / Threading.Timer ou Utilisation d’un thread avec une boucle while et un thread.

L’intervalle de pulsation est de 1 seconde.

while(!exit) { //do work Thread.Sleep(1000); } 

ou

 myTimer.Start( () => { //do work }, 1000); //pseudo code (not actual syntax)... 

System.Threading.Timer a mon vote.

System.Timers.Timer est conçu pour une utilisation sur serveur (votre code s’exécute en tant que serveur / service sur une machine hôte plutôt que d’être exécuté par un utilisateur).

Un thread avec une boucle While et une commande Thread.Sleep est vraiment une mauvaise idée étant donné l’existence de mécanismes de calculateur plus robustes dans .NET.

Les timers de serveur sont une créature différente des threads dormants.

D’une part, en fonction de la priorité de votre thread et de ce qui est en cours d’exécution, votre thread de veille peut ou non être réveillé et programmé pour s’exécuter à l’intervalle demandé. Si l’intervalle est suffisamment long et que la précision de la planification n’a pas vraiment d’importance, Thread.Sleep() est un choix raisonnable.

Les minuteurs, quant à eux, peuvent déclencher leurs événements sur n’importe quel thread, ce qui permet de meilleures capacités de planification. Le coût d’utilisation des timers est toutefois un peu plus complexe dans votre code – et le fait que vous ne puissiez pas contrôler quel thread exécute la logique déclenchée par l’événement du minuteur. De la documentation:

Le minuteur basé sur serveur est conçu pour être utilisé avec des threads de travail dans un environnement multithread. Les minuteurs de serveur peuvent se déplacer entre les threads pour gérer l’événement Elapsed déclenché, ce qui se traduit par une plus grande précision que les timers Windows dans la génération de l’événement à temps.

Une autre considération est que les temporisateurs invoquent leur délégué Elapsed sur un thread ThreadPool. En fonction de la durée et / ou de la complexité de votre logique, vous ne souhaiterez peut-être pas l’exécuter sur le pool de threads – vous souhaiterez peut-être créer un thread dédié. Un autre facteur avec les timers est que si le traitement prend suffisamment de temps, l’événement timer peut être relancé (simultanément) sur un autre thread – ce qui peut poser problème si le code en cours d’exécution n’est pas conçu pour la concurrence.

Ne confondez pas Server Timers avec ” Windows Timers “. Le dernier fait généralement référence à un message WM_TIMER qui peut être envoyé à une fenêtre, permettant à une application de planifier et de répondre au traitement temporisé sur son thread principal sans dormir. Toutefois, Windows Timers peut également faire référence à l’ API Win pour une synchronisation de bas niveau (différente de WM_TIMER).

Ni 🙂

Dormir est généralement mal vu (malheureusement, je ne me souviens pas des détails, mais pour un, c’est un “bloc” ininterrompu), et les Timer viennent avec beaucoup de bagages. Si possible, je recommanderais System.Threading.AutoResetEvent tant que tel

 // initially set to a "non-signaled" state, ie will block // if inspected private readonly AutoResetEvent _isStopping = new AutoResetEvent (false); public void Process() { TimeSpan waitInterval = TimeSpan.FromMilliseconds (1000); // will block for 'waitInterval', unless another thread, // say a thread requesting termination, wakes you up. if // no one signals you, WaitOne returns false, otherwise // if someone signals WaitOne returns true for (; !_isStopping.WaitOne (waitInterval); ) { // do your thang! } } 

L’utilisation d’un AutoResetEvent (ou de son cousin ManualResetEvent ) garantit un vrai bloc avec une signalisation sécurisée pour les threads (par exemple pour les terminaisons gracieuses ci-dessus). Au pire, c’est une meilleure alternative au Sleep

J’espère que cela t’aides 🙂

J’ai trouvé que la seule implémentation de minuteur qui est en réalité est System.Threading.Timer . Toutes les autres implémentations semblent plutôt fausses si vous traitez avec un nombre non négligeable d’éléments planifiés.