J'essaie d'appeler une méthode J'ai lu un peu sur les minuteries disponibles, mais je n'ai pas trouvé de bonne façon de faire ce que je veux, économiser pour l'écriture manuelle tout. Toute aide sur la manière de réaliser cela sera appréciée, même si je crains de ne pas pouvoir trouver une solution simple à l'aide de minuteries. P> à clarifier, si Notez que la nature de cette minuterie est que f () code> chaque
t code> heure, mais si l'invocation précédente de
f () code> n'a pas Terminé encore, attendez que ce soit fini.
t code> est une seconde, et
f () code> exécute les durées arbitraires que j'ai écrites ci-dessous, alors: p>
f () code> ne doit pas nécessairement être sûr en ce qui concerne l'entrée de la répétition et un bassin de tailles de taille 1 suffit ici. P> P>
8 Réponses :
Vous pouvez simplement utiliser un niveau de niveau «global» (ou plus probable, une propriété publique dans la même classe que donc si de cette façon de tirer chaque seconde, puis lance l'événement chronométré s'il ne manque pas déjà de Vous avez commenté que f () code>) qui retourne true si
f () code > est déjà en cours d'exécution.
f () code> était dans une classe nommée
TimeDevent code>, la première chose
f () code> Définir
exécuté code> true p>
if (! chronomévent.running) chronomevent.f () code> p>
f () code> ne répétera pas immédiatement s'il a fallu plus longtemps que l'intervalle de minuterie . C'est un point juste. J'inclurais probablement la logique comme celle-là intérieure
f () code> de sorte que
exécuter code> reste vrai. Donc, cela ressemblerait à ceci: P>
public void f(int t) // t is interval in seconds
{
this.running = true;
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
do
{
stopwatch.Reset();
// Do work here
} while (stopWatch.Elapsed.Seconds > t); // repeat if f() took longer than t
this.running = false;
}
Si vous faites cela, méfiez-vous des conditions de course.
Vrai, mais le questionneur a déclaré qu'il n'a pas besoin d'être multi-thread en toute sécurité
Très élégant, bien que cela signifie un 2e f code> ne suivra pas immédiatement un 10.5 seconde
f code>, n'est-ce pas? Cela attendra 0,5 seconde entre eux ...
@Paulg Le questionneur a déclaré qu'il ne veut pas passer de temps à faire du temps F code> thread-coffre-fort. Quel interrogateur signifiait par
f code> correspond à la partie "// fonctionne ici" partie de votre programme au lieu du
f code> dans votre programme. Vous devez vous assurer que votre
f code> fonctionne correctement même si le questionnaire
f code> n'est pas un fil-coffre-fort. Cependant, le fait est que votre programme lui-même n'est pas thread-coffre-fort, même si le
f code> est le fil-coffre-fort.
@Paulg Même définir exécutant code>
volatile code> ne fera pas votre code correct. Considérons la possibilité que votre
f code> soit préempté juste avant
this.running = true code> est exécuté.
@Gène. Vous pouvez améliorer la sécurité du thread en vérifiant «si (this.running) quitte» en haut de F (à l'intérieur d'une serrure s'il existe d'autres accessoires d'écriture à «exécuter»). Merci d'avoir attiré cela à mon attention avec votre bowvote. Comme dit plus tôt, l'ajout de la sécurité du thread n'était pas l'accent sur la question ou la réponse.
@Paulg non, ce n'est pas sûr. Voir mon commentaire précédent. Eh bien, je n'ai pas expliqué assez clair. Si vous le vérifiez simplement, il n'est absolument pas sûr, car la mémoire différente de la mémoire peut être différente en raison de registres et de cache. Si vous le définissez volatile, cela forcera une synchronisation à chaque fois que la variable est lue. Cela semble résoudre le problème, mais envisager la possibilité que vous cotrageez à droite après avoir vérifié exécutant code> mais avant de définir
exécuter code> à true. Vous avez besoin d'un verrou supplémentaire pour vous assurer que cela ne se produira pas.
@Paulg concernant 'Comme dit plus tôt, l'ajout de la sécurité du fil n'était pas l'accent sur la question ou la réponse ", je crois que j'ai expliqué mon raisonnement assez clair dans un commentaire précédent. L'OP ne veut pas f () code> réentrant et de sécurité, vous devez donc garantir
f () code> ne sera pas appelé deux fois. Et c'est pourquoi vous devez ajouter de la sécurité thread-sécurité à votre code.
Vous pouvez utiliser une minuterie non redémarrante, puis redémarrez manuellement la minuterie après la fin de la méthode. P>
Notez que cela entraînera du timing qui est quelque peu différent de ce que vous demandez. (Il y aura toujours un vide de Vous pouvez résoudre celui-ci en réglant l'intervalle sur méfiez-vous des conditions de race si vous devez arrêter la minuterie. P> T code> entre les invocations) p>
lasttick + t - maintenant code> et exécutant la méthode immédiatement si c'est
<= 0 p>. p>.
Vous ne pouvez pas obtenir une minuterie pour vous appeler exactement à intervalles réguliers. Toutes les minuteries font est de vous rappeler pas plus tôt que em> l'heure demandée. P>
Certaines minuteries sont meilleures que d'autres (par exemple, Windows.Forms.Timer est très irrégulière et peu fiable par rapport à System.threading.Timer) p>
Pour arrêter votre minuterie appelée à nouveau, une approche consiste à arrêter la minuterie pendant l'exécution de votre méthode. (Selon le type de minuterie que vous utilisez, arrêtez-le et recommencez à nouveau lorsque votre gestionnaire se déroule, ou avec quelques minuteries, vous pouvez demander un seul rappel plutôt que de répéter des rappels, chaque exécution de votre gestionnaire en aqueuse simplement l'appel suivant) . p>
Pour conserver le timing de manière relativement entre ces appels, vous pouvez enregistrer l'heure depuis la dernière exécution de votre gestionnaire et l'utiliser pour calculer le délai jusqu'à ce que le prochain événement soit requis. par exemple. Si vous souhaitez être appelé une fois par seconde et que votre minuterie a été remplie de providence à 1.02s, vous pouvez configurer le prochain rappel de la minuterie à une durée de 0,98s pour accueillir le fait que vous avez déjà "utilisé" une partie de la suivante. Deuxièmement lors de votre traitement. P>
Utilisez un système.Threading.Timer. Initialisez-le avec une période de délai d'attente.infinite afin qu'il agit comme une minuterie unique. Lorsque F () complète, appelez sa méthode Modifier () pour la recharger à nouveau. P>
Avez-vous voulu dire la période définie sur timeout.infinite code>?
une solution simple:
Que diriez-vous d'utiliser des délégués à la méthode F (), de la file d'attente à une pile et d'éclairer la pile à mesure que chaque délégué se termine? Vous avez toujours besoin de la minuterie, bien sûr. P>
Un fil simple est le moyen le plus simple d'y parvenir. Vous n'allez toujours pas être certain que votre appelé «précisément» quand vous le souhaitez, mais il devrait être proche ... vous pouvez également décider si vous souhaitez sauter des appels qui devraient EM> se produire ou tenter d'attraper Sauvegarder ... Voici une routine d'assistance simple pour créer le fil.
Pour le bénéfice des personnes qui atterrissent ici à la recherche de "retrénétrie": (Je sais que cela peut être trop tard pour la question initiale) Si l'on n'ait pas opposé à l'utilisation de bibliothèques open source qui prévoient déjà une telle fonctionnalité, je les ai réussies avec succès via une implémentation à l'aide de Quartz. NET Lorsque vous créez un travail et joignez un déclencheur, vous pouvez spécifier ce qui devrait être effectué si un déclencheur précédent n'a pas terminé l'exécution de son travail P>
Le lien est mort.
@rastroWalker merci! Enlevé pour le moment, car ce n'est pas vraiment nécessaire ici.