Mon application est assise dans la barre d'état système quand elle n'est pas utilisée. p>
L'utilisateur peut configurer des événements à survenir à la planification particulière. Par exemple, ils peuvent appartenir à la tâche effectuée le lundi au vendredi à 17h ou tous les mercredis à 15h00 ou le 16 de chaque mois à 10h00. P>
Assumer que mon programme Delphi est toujours en cours d'exécution, il commence à démarrer, quelle est la meilleure façon de Delphi d'appuyer le déclenchement de ces événements planifiés. P>
Évidemment, un Timer peut être utilisé pour planifier des événements basés sur le temps écoulé, mais ils ne semblent pas adaptés à ce problème. P>
acclamations p>
6 Réponses :
J'utiliserais l'API du planificateur de tâches Microsoft pour cela: p>
http://msdn.microsoft.com/fr -us / bibliothèque / AA383614 (vs.85) .aspx p>
Il y a des wrappers Delphi disponibles pour l'API si vous ne voulez pas faire le «travail sale», mais je ne sais pas s'il y a un gratuit. Vous pourriez avoir un coup d'oeil à p>
Si vous ne voulez pas utiliser le planificateur Microsoft, il existe des éléments tels que le composant Cronjob disponible ici: http://www.appcontrols.com/components.html . C'est aussi shareware, mais est facile à mettre en œuvre (juste un événement Onlert). P>
Comment laisserez-vous le planificateur de tâches Windows déclencher l'exécution des tâches dans l'exécutable déjà exécutable?
Code de l'application de manière à ce qu'il n'autorise qu'une seule instance. Si un autre instance est lancé (que l'approche du planificateur de tâches tenterait de faire), cette nouvelle instance peut transférer les informations pertinentes à l'instance existante d'Alreadu via une forme d'IPC (par exemple à l'aide de SendMessage) avant de quitter. Il n'a probablement pas de sens d'exécuter de multiples instances de l'application, alors rien n'est vraiment perdu en ajoutant une telle limitation.
HM OK, mais il semble lourd et une solution sujette erronée. Je dirais que cela dépend vraiment du problème à la main. Le planificateur Windows peut être assez bon ou même une solution parfaite, mais dans certains cas, il est totalement inapproprié.
Bien personnellement, je diviserais ma demande en deux exécutables: une qui ne fait rien d'autre que d'exécuter les tâches que les utilisateurs peuvent définir (et cette application est appelée par le planificateur) et à laquelle mes utilisateurs peuvent ajouter de nouvelles tâches, ce serait celui L'OP a constamment couru dans son plateau. La suggestion de Michaels est également une bonne idée, mais imo trop compliqué à mettre en œuvre :-)
@Michael: cette solution commence à regarder vraiment i> compliqué, que je pense est un signe certain que le planificateur de tâches Windows n'est que la mauvaise approche.
Vous avez besoin d'un composant de planification. Il y a Beaucoup de disponibilités , mais je ne peux pas sembler trouver gratuit . Vous pouvez toujours construire un vous-même, basé sur Timer, ou essayer d'accéder à API de planification des tâches. p>
Vous pouvez utiliser mon CRON CONFORIANT Cromis Scheduler (link à archiver.org). Il soutient même certaines choses que Cron ne le fait pas. Événements basés sur les intervalles par exemple et à partir de / à la période. Je l'utilise dans beaucoup de mon logiciel et cela s'est avéré très utile. C'est gratuit, très léger, fonctionne dans des fils et est testé de la production. Si vous avez besoin d'aide supplémentaire, envoyez-moi un mail. P>
Les autres manières seraient: p>
Je viens d'essayer cela et non seulement cela a-t-il gelé mon application de manière étrange (où même le débogueur n'a pas terminé l'application) mais a également laissé une fuite de mémoire méchante (et a dû redémarrer l'IDE à chaque fois que je l'ai couru).
Et il cycles de processeur porcine et même s'il fonctionne dans un fil secondaire pour une raison quelconque, il est enlaver mon fil principal. Et je l'ai fait fondamentalement rien que de montrer un message quand il déclenche. Juste mes deux cents. Ceci est un Delphi Xe2 fraîchement installé (et mis à jour) au moyen.
Pour le compte rendu, la fuite de mémoire était de ma faute, mais le reste des problèmes persistent toujours. CPU enlisé, le fil principal enlisé même si elle est utilisée dans un autre fil de travailleur et même de ne pas tirer des événements.
@Jerry, vous utilisez le type de signalisation STMESSAGE dans un fil sans pompe à message. Ce type de signalisation utilise PostMessage pour vous informer de l'événement et dans votre cas qui ne reçoit jamais de processus. Changez que pour STSYCHRONISE ou STHENED, ou créer une pompe à message dans le fil où vous avez créé le calendrier. Ou créer tous les horaires dans le fil principal.
Le site Web Cromis est un site de phishing maintenant. Quelqu'un semble avoir pris une sauvegarde du code et la mettre sur GitHub, mais je ne peux pas en garcer.
Vous pourriez mettre en œuvre une sorte de communication inter processus dans votre programme et déclencher ces événements via ipc par un programme appelé à partir du service de planification de Windows. Cette approche présente l'avantage de ne pas avoir besoin d'écrire une interface utilisateur pour configurer le calendrier et que IPC pourrait s'avérer utile d'une autre manière. P>
Étant donné que votre application est en cours d'exécution, vous pouvez utiliser l'événement de ralenti pour voir si une date / heure prédéfinie s'est déjà écoulée et, le cas échéant, d'effectuer votre timing. Le seul effet secondaire de cette approche est que votre événement ne se déclenche pas si l'application est occupée, mais non plus une minuterie (pour que TTIMER fonctionne la file d'attente de message doit être traitée, ou l'application doit être "inactive" sauf si vous utilisez une minuterie filetée).
uses
...,DateUtils; // contains IncMinute
type
TForm1 = Class(TForm)
:
procedure FormCreate(Sender: TObject);
private
fTargetDate : tDateTime;
procedure AppIdle(Sender: TObject; var Done: Boolean);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
fTargetDate := 0.0;
Application.OnIdle := AppIdle;
fTargetDate := IncMinute(Now,2);
end;
procedure TForm1.AppIdle(Sender: TObject; var Done: Boolean);
begin
if (fTargetDate <> 0.0) and (Now >= fTargetDate) then
begin
fTargetDate := 0.0;
ShowMessage('started');
end;
end;
Notez que vous appuyer uniquement sur onidle code> est dangereux, car cela sera appelé qu'après le dernier message en file d'attente pour l'une des fenêtres créées par le fil VCL a été traitée. S'il n'y a pas de messages, aucun traitement inactif n'a lieu. Si l'application est minimisée ou n'a aucune fenêtre visible et il n'y a pas de messages diffusés cela pourrait essentiellement signifier jamais.
Une autre option serait de créer une Ththread qui effectue la gestion de la minuterie: implémentation: p> qui peut alors être connecté jusqu'à la forme principale: p>
Mise en œuvre d'un thread pour un Ttimer? Ne crée pas de Timer un fil lui-même ?? Il n'y a donc aucun avantage par rapport à Onter ...
Seuls celui-ci ne fait pas des secondes, il ne se déclenche pas jusqu'à ce qu'une heure spécifique soit atteinte.
Avez-vous envisagé d'utiliser le planificateur de tâches intégré de Windows pour lancer votre programme avec un paramètre pour obtenir le démarrage de la tâche ou est-il important que la planification a lieu dans votre application?
Pourquoi considérer le temps écoulé? Avoir juste un seul feu de minuterie de temps en temps (une fois toutes les 10 secondes serait une résolution raisonnable). Une fois qu'il incendie, arrêtez temporairement la minuterie et parcourez votre liste d'événements planifiés. Vous connaissez l'heure et la journée actuelles, vous savez que chacun des événements planifiés a été licencié (si jamais) - il serait facile de tirer parti de chacun des événements devenus dus / en retard, et de redémarrer enfin votre minuterie. Je fais quelque chose de similaire à cela dans plusieurs programmes, et je pense que c'est votre voie la plus facile si vous voulez tout faire à Delphi.
@robsoft: Vous auriez dû faire cela une réponse à la place, ce que j'aurais voté. Avec la seule modification pour ne pas avoir le feu de la minuterie toutes les x secondes, mais de calculer dynamiquement l'intervalle à l'événement suivant.
Mon planificateur fait exactement ça. Il raccourcit la période d'attente comme elle s'approche de l'événement et utilise WaitforsingObject entre les deux.
@gghie - merci. Je m'attendais à beaucoup de gens de dire la même chose, seulement mieux, c'est pourquoi je ne me suis pas préoccupé de faire une réponse. Je vais savoir mieux la prochaine fois! La raison pour laquelle mes applications incendie régulièrement est simplement qu'il existe également d'autres activités régulières à la minuterie dans les programmes. Si ce n'était qu'un programme de lancement de quelques événements spécifiques à des heures prédéterminées, vous avez raison, vous pouvez simplement calculer de manière dynamique l'intervalle à l'événement suivant et avoir le feu de la minuterie pour cela.