Arrêt du temporisateur dans sa méthode de rappel
J'ai un Système.Le filetage.Timer qui appelle à son gestionnaire d'événement approprié (rappel) à chaque 10 ms. La méthode elle-même est non réentrant et peut parfois prendre façon de plus de 10 ms. Donc, je veux arrêter le chronomètre lors de l'exécution de la méthode.
Code:
private Timer _creatorTimer;
//BackgroundWorker's work
private void CreatorWork(object sender, DoWorkEventArgs e) {
_creatorTimer = new Timer(CreatorLoop, null, 0, 10);
//some other code that worker is doing while the timer is active
//...
//...
}
private void CreatorLoop(object state) {
//Stop timer (prevent reentering)
_creatorTimer.Change(Timeout.Infinite, 0);
/*
... Work here
*/
//Reenable timer
_creatorTimer.Change(10, 0);
}
MSDN indique que la méthode de rappel est appelée chaque fois que le timer se déclenche) dans le thread du pool de threads. Cela signifie que si j'arrêt de la minuterie, la première chose dans la méthode elle n'est pas toujours impérativement prévenir la minuterie à feu et à exécuter un autre exemple de la méthode avant de la première, avait une chance d'arrêter la minuterie.
Devrait peut-être que la minuterie (ou même la non réentrante de la méthode elle-même) être verrouillée?
Quelle est la bonne façon de prévenir la minuterie de cuisson lors de l'exécution de son rappel (et non réentrant) méthode?
source d'informationauteur Kornelije Petak
Vous devez vous connecter pour publier un commentaire.
Vous pourriez vous laisse le temps de continuer la cuisson de la méthode de rappel d'envelopper votre non réentrant code dans un Moniteur.TryEnter/Sortie. Pas besoin de s'arrêter/redémarrer le compte à rebours dans ce cas; le chevauchement des appels ne seront pas acquérir le verrou et de revenir immédiatement.
Quelques solutions possibles:
Vous pouvez être en mesure de gérer l'option n ° 2 sans disposer/création d'un nouvel objet à l'aide de la
Change()
méthode de l'original de l'objet timer, mais je ne suis pas sûr de ce que le comportement est exactement à l'appel deChange()
avec un nouveau délai d'attente de démarrage après le premier délai d'attente a expiré. Que serait la valeur d'un test ou deux.Edit:
J'ai fait le test de la manipulation de la minuterie comme un redémarrage one-shot semble fonctionner parfaitement, et c'est beaucoup plus simple que les autres méthodes. Voici un exemple de code basé sur le vôtre, en tant que point de départ (un peu de détails ont peut-être changé pour la compiler sur ma machine):
J'ai eu la même situation avec un Système.Les minuteries.À rebours, où le temps écoulé événement est exécuté à partir d'un pool de threads et doit être réentrant.
J'ai utilisé cette méthode pour contourner le problème:
En fonction de ce que vous faites, vous pourriez envisager d'utiliser un Système.Les minuteries.Minuterie, voici un bon résumé de MSDN
Je le fais avec Contrefil qui propose des opérations atomiques, et par CompareExchange assure qu'un seul thread à la fois entre la section critique: