Je voulais une minuterie avec les propriétés suivantes:
Peu importe combien de fois le démarrage est appelé, un seul fil de rappel est toujours en cours d'exécution p> li>
Le temps passé dans la fonction de rappel a été ignoré en ce qui concerne l'intervalle. E.g Si l'intervalle est de 100 ms et que le rappel prend 4 000 ms pour exécuter, le rappel est appelé à 100 ms, 4100ms, etc. p> li> ol>
Je n'ai pas pu voir quoi que ce soit disponible, a écrit le code suivant. Y a-t-il une meilleure façon de faire cela? P>
/** * Will ensure that only one thread is ever in the callback */ public class SingleThreadedTimer : Timer { protected static readonly object InstanceLock = new object(); //used to check whether timer has been disposed while in call back protected bool running = false; virtual new public void Start() { lock (InstanceLock) { this.AutoReset = false; this.Elapsed -= new ElapsedEventHandler(SingleThreadedTimer_Elapsed); this.Elapsed += new ElapsedEventHandler(SingleThreadedTimer_Elapsed); this.running = true; base.Start(); } } virtual public void SingleThreadedTimer_Elapsed(object sender, ElapsedEventArgs e) { lock (InstanceLock) { DoSomethingCool(); //check if stopped while we were waiting for the lock, //we don't want to restart if this is the case.. if (running) { this.Start(); } } } virtual new public void Stop() { lock (InstanceLock) { running = false; base.Stop(); } } }
5 Réponses :
Voici un exemple rapide que je viens de frapper;
Bonne réponse et merci. Je me promenais ce qui se produirait si deux threads ont appelé la routine de départ simultanément?
@RICHARD FAIR POINT, la réponse ne fonctionnerait de manière fiable que pour une seule application filetée. J'ai édité ma réponse pour donner une idée de l'endroit où le verrouillage entrerait en jeu. Vous pouvez toujours verrouiller (ceci) à la place si vous préférez.
@Richard: Pour vous assurer qu'un seul thread d'appelera la routine de départ à un moment donné, vous pouvez utiliser Mutex. Vous trouverez plus de détails ici MSDN.MicRosoft.com/en-us/Library/ MS173179.aspx
Regardez le Vous pouvez avoir une pile à l'intérieur de votre classe de temps et que vous pourriez implémenter une méthode du moniteur () qui renvoie une option isolable. Vous pouvez ainsi utiliser le la minuterie comme: p> avez le moniteur de la minuterie enfoncé l'horodatage d'intervalle éteint la pile pendant le disposer (). p> codant manuellement tout le verrouillage et La reconnaissance du fil est une option comme cela a été mentionné. Cependant, le verrouillage influencera le temps utilisé, probablement plus que de devoir initialiser une instance par fil à l'aide de ThreadLocal P> si vous êtes intéressé, je pourrais assommer un exemple plus tard P> P> [ThreadStatic] Code> Attribut et le type générique ThreadLocal .NET 4.0. Cela vous donnera probablement rapidement un moyen de coder cela sans gâcher avec le verrouillage du fil, etc.
Le .NET Framework fournit Les deux autres sont spéciales Les 2 derniers sont conçus pour éliminer les problèmes de sécurité Par exemple, en utilisant WebBrowser Strong> à l'intérieur d'une minuterie pour capturer des captures d'écran à partir de la page Web doit être unifaminé et donne une erreur au moment de l'exécution s'il s'agit d'un autre fil. P>
Les minuteries à threads unique ont les suivants et principal désavantage fort> à noter p>
source : la plupart sont des restes de
Pour quiconque a besoin d'une seule minuterie de thread et que la minuterie commence à cocher après la tâche em>.
System.Timers.Timer pourrait faire le tour sans verrouillage ni [threadstatique] crédit sur Alan N
Source https://www.codeproject.com / Réponses / 405715 / System-Timers-Timers-Offre-usage-usage # Réponse2 P> Edit: Espacement P> P>
Voici un simple Exemple d'utilisation. Montre comment créer une minuterie non superposé qui commence immédiatement, avec une période de 10 secondes. P> au cas où le Le périodiquenonoverlappeMer code>, qui fournit uniquement les fonctionnalités demandées, et rien de plus que cela. Cette minuterie ne peut être démarrée et arrêtée à la demande, et aucun intervalle n'a été modifié. Il invoque simplement l'action spécifiée périodiquement d'une manière non superposée, jusqu'à ce que la minuterie soit disposée.
DosomoolCool code> échoue, l'exception sera lancé sur le
threadpool code> , causant le processus de crash. Donc, vous voudrez peut-être ajouter un
essayer code> /
bloc code> et gérer toutes les exceptions pouvant survenir. P>
Dispose code > est une méthode potentiellement bloquante. Si la périodicaction code> est en cours d'exécution, le
Dispose code> bloquera jusqu'à la fin de la dernière invocation.
Si vous ne voulez pas attendre que cela se produise, vous pouvez le faire à la place: P>
_ = timer.DisposeAsync(); // Stop the timer without waiting it to finish
Un peu quelque peu connexe: exécuter la méthode Async régulièrement avec intervalle spécifié