web-dev-qa-db-fra.com

Méthode d'exécution à toutes les heures

Je veux exécuter une méthode toutes les heures. J'ai écrit du code, mais ce n'est pas suffisant pour mon objectif. Le code ci-dessous fonctionne toutes les 60 minutes. 

public void Start()
{
    System.Threading.Timer timerTemaUserBilgileri = new System.Threading.Timer(new System.Threading.TimerCallback(RunTakip), null, tmrTemaUserBilgileri, 0);
}

public void RunTakip(object temauserID)
{
    try 
    {
        string objID = "6143566557387";
        EssentialMethod(objID);
        TimeSpan span = DateTime.Now.Subtract(lastRunTime);
        if (span.Minutes > 60)
        {
            tmrTemaUserBilgileri = 1 * 1000;
            timerTemaUserBilgileri.Change(tmrTemaUserBilgileri, 0);
        }
        else
        {
            tmrTemaUserBilgileri = (60 - span.Minutes) * 60 * 1000;
            timerTemaUserBilgileri.Change(tmrTemaUserBilgileri, 0);
        }
        watch.Stop();
        var elapsedMs = watch.ElapsedMilliseconds;
    }
    catch (Exception ex)
    {
        timerTemaUserBilgileri.Change(30 * 60 * 1000, 0);
        Utils.LogYaz(ex.Message.ToString());
    }
}

public void EssentialMethod(objec obj)
{
    //some code
    lastRunTime = DateTime.Now;
    //send lastruntime to sql 
}
9
RockOnGom

Si vous voulez que votre code soit exécuté toutes les 60 minutes:

aTimer = new System.Timers.Timer(60 * 60 * 1000); //one hour in milliseconds
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
    //Do the stuff you want to be done every hour;
}

si vous voulez que votre code soit exécuté toutes les heures (par exemple, 1:00, 2:00, 3:00), vous pouvez créer une minuterie avec un petit intervalle (disons une seconde, dépend de la précision dont vous avez besoin) et à l'intérieur de cet événement vérifier si une heure s'est écoulée

aTimer = new System.Timers.Timer(1000); //One second, (use less to add precision, use more to consume less processor time
int lastHour = DateTime.Now.Hour;
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
    if(lastHour < DateTime.Now.Hour || (lastHour == 23 && DateTime.Now.Hour == 0))
     {
           lastHour = DateTime.Now.Hour;
           YourImportantMethod(); // Call The method with your important staff..
     }

}
19
Anarion

Juste un petit commentaire basé sur/la solution d'Anarion que je ne pouvais pas intégrer dans un commentaire.

vous pouvez créer une minuterie avec un petit intervalle (disons une seconde, cela dépend de la précision dont vous avez besoin) 

Vous n'en avez pas besoin pour aller avec précision, vous vous demandez "comment puis-je vérifier cette heure est l'heure à laquelle je veux tirer". Vous pouvez aussi penser "Comment puis-je vérifier l'heure suivante est l'heure que je veux tirer" - une fois que vous pensez comme ça, vous réalisez que vous n'avez besoin d'aucune précision, cochez simplement une fois par heure et définissez un fil pour le heure prochaine Si vous cochez une fois par heure, vous saurez que vous le serez avant la prochaine heure.

Dim dueTime As New DateTime(Date.Today.Year, Date.Today.Month, Date.Today.Day, DateTime.Now.Hour + 1, 0, 0)
Dim timeRemaining As TimeSpan = dueTime.Subtract(DateTime.Now)

t = New System.Threading.Timer(New System.Threading.TimerCallback(AddressOf Method), Nothing, CType(timeRemaining.TotalMilliseconds, Integer), System.Threading.Timeout.Infinite)
5
Paul Hutchinson

Je suis d’accord avec Señor Salt pour dire que le chron job devrait être le premier choix. Cependant, le PO a demandé chaque heure à partir de c #. Pour ce faire, j'ai configuré le premier événement chronométré pour qu'il se déclenche à l'heure indiquée:

int MilliSecondsLeftTilTheHour()
{
    int interval;

    int minutesRemaining = 59 - DateTime.Now.Minute;
    int secondsRemaining = 59 - DateTime.Now.Second;
    interval = ((minutesRemaining * 60) + secondsRemaining) * 1000;

    // If we happen to be exactly on the hour...
    if (interval == 0)
    {
        interval = 60 * 60 * 1000;
    }
    return interval;
}

Timer timer = new Timer();
timer.Tick += timer_Tick;
timer.Enabled = true;
timer.Interval = MilliSecondsLeftTilTheHour();

Le problème est maintenant que si la minuterie ci-dessus.Interval se trouve être de 45 minutes et 32 ​​secondes, alors la minuterie continuera à tirer toutes les 45:32 pas seulement la première fois. Ainsi, dans la méthode timer_Tick, vous devez réajuster le timer.Interval à une heure. 

 void timer_Tick(object sender, EventArgs e)
 {
     // The Interval could be hard wired here to  60 * 60 * 1000 but on clock 
     // resets and if the job ever goes longer than an hour, why not
     // recalculate once an hour to get back on track.
     timer.Interval = MilliSecondsLeftTilTheHour();
     DoYourThing();
 }
4
EscapeArtist

Utiliser une tâche cron sur le serveur pour appeler une fonction à l'intervalle spécifié 

Voici un lien http://www.thesitewizard.com/general/set-cron-job.shtml

1
John Richard Salt

Que diriez-vous de quelque chose de plus simple? Utilisez une minuterie d’une minute pour vérifier l’heure:

public partial class Form1 : Form
{
    int hour;
    public Form1()
    {
        InitializeComponent();

        if(RunOnStartUp)
            hour = -1;
        else
            hour = DateTime.Now.Hour;

    }
    private void timer1_Tick(object sender, EventArgs e)
    {
        // once per minute:
        if(DateTime.Now.Hour != hour)
        {
            hour = DateTime.Now.Hour;
            DailyTask();
        }
    }
    private DailyTask()
    {
        // do something
    }
}
1
user3235770

Pourquoi ne pas essayer le code ci-dessous, la boucle est déterminée à économiser vos ressources et elle s'exécute toutes les heures EXACT, c’est-à-dire avec les minutes et les secondes (et presque millisecondes égales à zéro:

using System;
using System.Threading.Tasks;

namespace COREserver{
    public static partial class COREtasks{   // partial to be able to split the same class in multiple files
        public static async void RunHourlyTasks(params Action[] tasks)
        {
            DateTime runHour = DateTime.Now.AddHours(1.0);
            TimeSpan ts = new TimeSpan(runHour.Hour, 0, 0);
            runHour = runHour.Date + ts;


            Console.WriteLine("next run will be at: {0} and current hour is: {1}", runHour, DateTime.Now);
            while (true)
            {
                TimeSpan duration = runHour.Subtract(DateTime.Now);
                if(duration.TotalMilliseconds <= 0.0)
                { 
                    Parallel.Invoke(tasks);
                    Console.WriteLine("It is the run time as shown before to be: {0} confirmed with system time, that is: {1}", runHour, DateTime.Now);
                    runHour = DateTime.Now.AddHours(1.0);
                    Console.WriteLine("next run will be at: {0} and current hour is: {1}", runHour, DateTime.Now);
                    continue;
                }
                int delay = (int)(duration.TotalMilliseconds / 2);
                await Task.Delay(30000);  // 30 seconds
            }
        }
    }
}
0
Hasan A Yousef

Pourquoi tout le monde essaie de gérer ce problème avec une minuterie?

vous faites deux choses ... attendre le début de l'heure, puis activez votre chronomètre toutes les heures.

J'ai un service Windows où j'avais besoin de cette même solution. J'ai fait mon code d'une manière très verbeuse afin qu'il soit facile à suivre pour n'importe qui. Je sais que de nombreux raccourcis peuvent être mis en place, mais je vous laisse le soin.

private readonly Timer _timer;
/// starts timer
internal void Start()
{
    int waitTime = calculateSleepTime();

    System.Threading.Thread.Sleep(waitTime);

    object t = new object();

    EventArgs e = new EventArgs();

    CheckEvents(t, e);

    _timer.Start();
}

///  runs business logic everytime timer goes off
internal void CheckEvents(object sender, EventArgs e)
{
    //  do your logic here      
}

///  Calculates how long to wait until the top of the hour
private int calculateSleepTime()
{
    DateTime now = DateTime.Now;

    int minutes = now.Minute * 60 * 1000;

    int seconds = now.Second * 1000;

    int substrahend = now.Millisecond + seconds + minutes;

    int minuend = 60 * 60 * 1000;

    return minuend - substrahend;
}         
0
Evander