Mise à jour :
Près de quatre ans après ma réponse initiale et cette réponse est très obsolète. Depuis TopShelf est arrivé, le développement des services Windows est devenu facile. Il ne vous reste plus qu'à trouver comment supporter le basculement...
Réponse originale :
Je ne suis vraiment pas un fan de Windows Scheduler. Le mot de passe de l'utilisateur doit être fourni comme @moodforall comme indiqué ci-dessus, ce qui est amusant lorsque quelqu'un change le mot de passe de cet utilisateur.
L'autre inconvénient majeur de Windows Scheduler est qu'il fonctionne de manière interactive et non en tant que processus d'arrière-plan. Lorsque 15 fenêtres MS-DOS apparaissent toutes les 20 minutes pendant une session RDP, vous vous en voudrez de ne pas les avoir installées en tant que services Windows.
Quel que soit votre choix, je vous recommande vivement de séparer votre code de traitement dans un composant différent de l'application console ou du service Windows. Ensuite, vous avez le choix entre appeler le processus de travail à partir d'une application console et le connecter au planificateur Windows, ou utiliser un service Windows.
Vous constaterez que la programmation d'un service Windows n'est pas une partie de plaisir. Un scénario assez courant est celui d'un processus de longue durée que vous souhaitez exécuter périodiquement. Mais, si vous traitez une file d'attente, vous ne voulez vraiment pas que deux instances du même travailleur traitent la même file d'attente. Vous devez donc gérer la minuterie, afin de vous assurer que si votre processus long s'est exécuté plus longtemps que l'intervalle de minuterie assigné, il ne redémarre pas avant que le processus existant ne soit terminé.
Après avoir écrit tout cela, vous vous dites : pourquoi n'ai-je pas simplement utilisé Thread.Sleep ? Cela me permet de laisser le thread en cours d'exécution jusqu'à ce qu'il ait terminé, puis l'intervalle de pause se déclenche, le thread se met en sommeil et redémarre après le temps requis. C'est génial !
Vous lisez ensuite tous les conseils sur l'internet, où de nombreux experts vous disent que c'est une très mauvaise pratique de programmation :
http://msmvps.com/blogs/peterritchie/archive/2007/04/26/thread-sleep-is-a-sign-of-a-poorly-designed-program.aspx
Alors vous vous grattez la tête et vous vous dites : "WTF, annuler les caisses en attente -> Oui, je suis sûr -> annuler tout le travail d'aujourd'hui..... damn, damn, damn....".
Cependant, j'aime ce modèle, même si tout le monde pense que c'est de la merde :
Méthode OnStart pour l'approche à fil unique.
protected override void OnStart (string args) {
// Create worker thread; this will invoke the WorkerFunction
// when we start it.
// Since we use a separate worker thread, the main service
// thread will return quickly, telling Windows that service has started
ThreadStart st = new ThreadStart(WorkerFunction);
workerThread = new Thread(st);
// set flag to indicate worker thread is active
serviceStarted = true;
// start the thread
workerThread.Start();
}
Le code instancie un thread séparé et attache notre travailleur à celui-ci. Ensuite, il démarre le thread et laisse l'événement OnStart se terminer, afin que Windows ne pense pas que le service est suspendu.
Méthode de travail pour l'approche à fil unique.
/// <summary>
/// This function will do all the work
/// Once it is done with its tasks, it will be suspended for some time;
/// it will continue to repeat this until the service is stopped
/// </summary>
private void WorkerFunction() {
// start an endless loop; loop will abort only when "serviceStarted"
// flag = false
while (serviceStarted) {
// do something
// exception handling omitted here for simplicity
EventLog.WriteEntry("Service working",
System.Diagnostics.EventLogEntryType.Information);
// yield
if (serviceStarted) {
Thread.Sleep(new TimeSpan(0, interval, 0));
}
}
// time to end the thread
Thread.CurrentThread.Abort();
}
Méthode OnStop pour l'approche à fil unique.
protected override void OnStop() {
// flag to tell the worker process to stop
serviceStarted = false;
// give it a little time to finish any pending work
workerThread.Join(new TimeSpan(0,2,0));
}
Fuente: http://tutorials.csharp-online.net/Creating_a_.NET_Windows_Service%E2%80%94Alternative_1%3a_Use_a_Separate_Thread (Lien mort)
Je fais fonctionner de nombreux services Windows de cette manière depuis des années et cela me convient parfaitement. Je n'ai toujours pas vu de modèle recommandé sur lequel les gens sont d'accord. Faites simplement ce qui fonctionne pour vous.