web-dev-qa-db-fra.com

C #: comment démarrer un thread à un moment précis

Comment puis-je démarrer un fil d'arrière-plan à une heure précise de la journée, par exemple 16h00?

Ainsi, lorsque les applications démarreront, le thread attendra jusqu'à ce moment. Mais si l'application démarre après cette heure, le thread s'exécutera immédiatement

ThreadPool.QueueUserWorkItem(MethodtoRunAt1600);

32
Bob

Vous pouvez configurer une minuterie à 16:00. J'ai répondu à une question similaire ici . Cela devrait vous aider à coup sûr.

private System.Threading.Timer timer;
private void SetUpTimer(TimeSpan alertTime)
{
     DateTime current = DateTime.Now;
     TimeSpan timeToGo = alertTime - current.TimeOfDay;
     if (timeToGo < TimeSpan.Zero)
     {
        return;//time already passed
     }
     this.timer = new System.Threading.Timer(x =>
     {
         this.SomeMethodRunsAt1600();
     }, null, timeToGo, Timeout.InfiniteTimeSpan);
}

private void SomeMethodRunsAt1600()
{
    //this runs at 16:00:00
}

Ensuite, configurez-le en utilisant

SetUpTimer(new TimeSpan(16, 00, 00));

Edit: Conservez la référence du Timer car il est sujet à la récupération de place, que le Timer soit actif ou non.

55
Sriram Sakthivel

Je voudrais utiliser Job Scheduling Library comme Quartz ou simplement créer une application console et l'exécuter en utilisant le planificateur de tâches Windows à l'heure spécifique de la journée.

Pourquoi ne pas simplement utiliser System.Timers.Timer?

  • Les minuteries n'ont aucun mécanisme de persistance.
  • Les minuteries ont une planification rigide (uniquement capable de définir l'heure de début et l'intervalle de répétition, rien en fonction des dates, de l'heure, etc.
  • Les minuteurs n'utilisent pas de pool de threads (un thread par minuteur)
  • Les minuteries n'ont pas de véritables schémas de gestion - vous devez écrire votre propre mécanisme pour pouvoir vous souvenir, organiser et récupérer vos tâches par nom, e
10
Damith

vous pouvez le faire avec une minuterie:

public class OncePerDayTimer : IDisposable
{
    private DateTime _lastRunDate;
    private TimeSpan _time;
    private Timer _timer;
    private Action _callback;

    public OncePerDayTimer(TimeSpan time, Action callback)
    {
        _time = time;
        _timer = new Timer(CheckTime, null, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1));
        _callback = callback;
    }

    private void CheckTime(object state)
    {
        if (_lastRunDate == DateTime.Today)
            return;

        if (DateTime.Now.TimeOfDay < _time)
            return;

        _lastRunDate = DateTime.Today;
        _callback();
    }

    public void Dispose()
    {
        if (_timer == null)
            return;

        _timer.Dispose();
        _timer = null;
    }
}
7
jgauffin

Toute solution qui dépend de System.Timers.Timer, System.Threading.Timer, ou l'un des autres temporisateurs qui existent actuellement dans le .NET Framework échouera face aux changements d'heure d'été. Si vous utilisez l'un de ces temporisateurs, vous devrez effectuer un sondage.

Windows a un Waitable Timer que vous pouvez utiliser, mais il n'est pris en charge par aucune classe Framework. J'ai écrit un emballage pour cela il y a quelques années. L'article que j'ai publié n'est plus disponible, mais vous pouvez télécharger le code source complet sur http://www.mischel.com/pubs/waitabletimer.Zip

Cela dit, si la seule chose que votre programme fait est exécutée une fois par jour, ou si la tâche qu'il exécute peut être séparée du reste du programme, vous êtes presque certainement mieux avec une tâche planifiée. Et même si je n'ai jamais utilisé Quartz.NET, je n'ai aucun problème à le recommander sur la base des bonnes critiques que j'ai vues de personnes dont je fais confiance.

6
Jim Mischel

Voici un moyen simple de planifier une méthode à appeler une fois, immédiatement ou à 16h00.

var runAt = DateTime.Today + TimeSpan.FromHours(16);
if(runAt < DateTime.Now)
{
    MethodtoRunAt1600();    
}
else
{
    var dueTime = runAt - DateTime.Now;
    var timer = new System.Threading.Timer(_ => MethodtoRunAt1600(), null, dueTime, TimeSpan.Zero); 
} 
1
Steve Ruble

Si vous cherchez quelque chose de "rapide et sale" ... alors vous pouvez simplement démarrer votre thread dans le pool de threads et "attendre" le bon moment.

// By the way, this code would be *INSIDE* of the background thread. That's what
// the sentence above says, but apparently we devs only read code :)
while (DateTime.Now.TimeOfDay < myDesiredStartTime)
{
    Thread.Sleep(1000);
}
1
Timothy Khouri

Pouvons-nous utiliser comme ça?

DispatcherTimer timer ;
// When application is started
if (DateTime.Now.Hour == 16)
{
   // Start your task
}
else
{
    timer = new DispatcherTimer();
    timer.Interval = new TimeSpan(0, 1, 0);
    timer.Tick += timer_Tick;
    timer.Start();
}

Ensuite, vérifiez pour chaque minute ..

void timer_Tick(object sender, EventArgs e)
{
    if (DateTime.Now.Hour == 16)
    {
        // Start your task
    }
}
0
Naren

Une solution très simple:

if (DateTime.Now.Hour > 16)
{
    MethodtoRunAt1600();
}
else
{
    var next16 = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 16, 0, 0);
    var timer = new Timer(MethodtoRunAt1600, null, next16 - DateTime.Now, TimeSpan.FromHours(24));
    timer.Start()
}
0
Jordy Langen

C'est quelque chose que j'ai utilisé pour réaliser ce type de fonctionnalité. http://www.codeproject.com/Articles/12117/Simulate-a-Windows-Service-using-ASP-NET-to-run-sc

0
Ali Umair

1- Appelez votre candidature depuis un autre processus

System.Diagnostics.Process.Start("CMD MyApplication.exe", "/C TIME 16:00");

2- Utilisez Timer et toutes les 1 minute vérifiez l'heure actuelle.

3- Gérez l'événement de changement d'heure de Windows dans votre application et vérifiez à chaque fois l'heure actuelle plus d'informations:

http://msdn.Microsoft.com/en-us/library/Microsoft.win32.systemevents.timechanged%28v=vs.100%29.aspx

J'espère que l'un d'entre eux vous aidera.

0
Bassam Alugili