Question

J'ai un timer comme défini ci-dessous.Le minuteur s'exécute une longue tâche en cours d'exécution.Le problème que j'ai, c'est quand la minuterie est en cours d'exécution de l'intervalle de nouveau et un autre minuterie de démarrage de l'exécution de je.e _timer_Elapsed.Comment puis-je obtenir la minuterie à l'exécution d'un intervalle après le compte à rebours est terminé.La façon dont il est maintenant, il pourrait y avoir plusieurs minuterie exécutions qui se passe à la fois et qui provoque toutes sortes de problèmes avec mon code.

protected override void OnStart(string[] args)
        {

           _timer = new System.Timers.Timer();
           _timer.AutoReset = false;
           _timer.Interval = (Convert.ToInt32(ConfigurationManager.AppSettings["CheckInterval"]));
           _timer.Elapsed += new System.Timers.ElapsedEventHandler(_timer_Elapsed);
           _timer.Enabled = true;
           _timer.Start(); // Start timer 

        }


 public static void _timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            try
            {
                _timer.Interval = (Convert.ToInt32(ConfigurationManager.AppSettings["CheckInterval"])); 

                BLLGenericResult SystemCheckItems_Result = ServiceItemOperations.CheckItems(); // Long Running Task

            }
            catch (Exception ex)
            {
                // Exception handling...
            }
            finally
            {
                _timer.Start();
            }
        }
Était-ce utile?

La solution

Nous allons écrire correctement cette.C'est l'Intervalle mission qui est de vous amener des ennuis.Un exemple de programme qui illustre le problème:

using System;

class Program {
    static System.Timers.Timer timer;
    static void Main(string[] args) {
        timer = new System.Timers.Timer();
        timer.AutoReset = false;
        timer.Interval = 1000;
        timer.Elapsed += timer_Elapsed;
        timer.Start();
        Console.ReadLine();
    }

    static void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) {
        timer.Interval = 1000;
        Console.WriteLine("Tick");
    }
}

Sortie:

Tick
Tick
Tick
...

Suppression de l'Intervalle de cession dans le temps Écoulé gestionnaire d'événements pour voir la différence.

Donc, en d'autres mots, même si la propriété est AutoReset faux, juste de l'affectation de la propriété Interval est suffisant pour obtenir le temporisateur de redémarrage.Grosse surprise bien sûr, personne ne les voit jamais venir.Et il fait des ravages sur votre programme parce que vous attribuez à la propriété d'Intervalle au début, avant vous commencez à faire le levage lourd.Ainsi, le temps Écoulé de l'événement seront de nouveau soulevée, sur un autre fil, tandis que votre précédente n'est pas terminée encore.C'est un filetage bug en attente de se produire, en particulier si la valeur de l'Intervalle est trop petit.Vous devez le définir plus tard, le faire à l'intérieur de la enfin le bloc.Bonne chose que vous faites l'Intervalle de temps trop petite, très difficile à diagnostiquer plus tard.

est-ce un c# bug ?

Le langage C# est à côté de la plaque, c'est une .NET Framework bug.Système.Les minuteries.La minuterie est en général pas une très bonne classe, il a de la facilité d'utilisation d'une scie à chaîne sans un interrupteur de sécurité.Il était destiné à rendre le Système.Le filetage.Classe Timer plus utilisable, en particulier la résolution d'un problème avec l'habitude d'être les ordures collectées trop tôt.Un problème résolu, mais trois nouveaux problèmes ajouté.Cela remonte à l' .NET 1.0, une version avec des roues de formation.Ils juste ne peut pas le fixer plus, trop de code existant de casser.Vous êtes vraiment mieux avec le Système.Le filetage.Minuterie, assurez-vous de garder de l'objet référencé dans une variable.Comme vous le faites déjà.

Autres conseils

2017 mise à jour:

Il est un nouvel outil qui peut être utile avec ce genre de problèmes.

await Task.Delay(TimeSpan.FromSeconds(x)); 
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top