Fonction SetWaitableTimer

L_art_ment Messages postés 302 Date d'inscription vendredi 21 septembre 2007 Statut Membre Dernière intervention 6 février 2013 - 2 juil. 2009 à 15:54
L_art_ment Messages postés 302 Date d'inscription vendredi 21 septembre 2007 Statut Membre Dernière intervention 6 février 2013 - 2 juil. 2009 à 19:03
Mes cieux d'âmes,

Je vous reviens avec une merveilleuse question, sur laquelle je me casse la tête depuis quelques heures... J'm'en va vous expliquer :

Mon but est de pouvoir mettre en veille un poste (veille normale ou veille prolongée), et de le reveiller; jusque là, j'y parviens, j'arrive à mettre en veille et à le reveiller en choisissant mon interval, par exemple 10secondes, pour ce faire, j'utilise cette procedure :

//Mise en veille
procedure standby;
  begin
    if IsPwrSuspendAllowed then
      SetSuspendState(false, false, false) //le premier parametre, s'il vaut true alors Veille prolongée
    else
      MessageDlg('La mise en veille n'est pas gérée sur ce system.', mtWarning, [mbOK], 0);
  end;

Pour déclencher la remise en route, j'utilise les evenement "d'alimentation" et les thread de cette manière :

//Cette fonction va detecter la mise en veille (ou veille prolongée), et va lancer le thread avec le délai avant la remise en route
procedure TForm1.WMPowerBroadcast(var Msg: TMessage);
begin


  //Check for suspend operation
  case Msg.wParam of
     //Query for allowing suspend
     PBT_APMQUERYSUSPEND     :  ;

     PBT_APMSUSPEND          :  TWakeupThread.Create(-400000000); // Ici je detecte la veille 
     // Resuming from event, we want monitor display
     PBT_APMRESUMEAUTOMATIC  :  SetThreadExecutionState(ES_DISPLAY_REQUIRED);
     PBT_APMSTANDBY          :  TWakeupThread.Create(-400000000);  //detect veille prolongée
  end;


  // Set message result
  Msg.Result:=1;


end;

//Création du thread
constructor TWakeupThread.Create(Time: Int64);
begin
inherited Create(False);
FreeOnTerminate:=True;
FTime:=Time;
end;

//Execution
procedure TWakeupThread.Execute;
var  hTimer:     THandle;
begin


  // Create a waitable timer.
  hTimer:=CreateWaitableTimer(nil, True, 'WaitableTimer');
  if (hTimer <> 0) then
  begin
     if (SetWaitableTimer(hTimer, FTime, 0, nil, nil, True)) then
     begin
      WaitForSingleObject(hTimer, INFINITE);
   end;
  CloseHandle(hTimer);
  end;


end;

Donc en résumé, quand on detect la mise en veille, on déclanche le timer pour un délai souhaité, à la fin du délai, le paramétre à True de la fonction SetWaitableTimer permet la remise en route du system, si il était à False, ca resterai en veille...

Mais moi ce que j'aimerai, c'est remettre en route le system, à l'heure que je désire... J'ai vu dans la MSDN que le paramétre FTime de la fonction SetWaitableTimer pouvait être une heure (si j'ai bien compris) : http://msdn.microsoft.com/en-us/library/ms686289(VS.85).aspx

mais je ne parvient pas à utiliser cette fonction de cette manière et n'ai trouvé aucun exemple... Et c'est là que je solicite vos lumiéres !

J'ai pourtant essayé une methode palliative mais qui ne fonctionne pô (l'idée étant d'executer le timer avec SetWaitableTimer avec le paramétre false tant qu'il ne trouve pas dans l'heure actuelle l'heure à laquelle je veux redémarrer le system, si il le trouve il execute le timer avec le paramétre true), la voici :
//Execution
procedure TWakeupThread.Execute;
var  hTimer:     THandle;
begin


  // Create a waitable timer.
  hTimer:=CreateWaitableTimer(nil, True, 'WaitableTimer');
  while (hTimer <> 0) do
     begin
     if (SetWaitableTimer(hTimer, FTime, 0, nil, nil, False)) then
     begin
      WaitForSingleObject(hTimer, INFINITE);
      if pos('10:30',DateTimeToStr(gettime))<>0 then
         begin
         closeHandle(hTimer);
         hTimer:=0;
         end
   end;
   
hTimer:=CreateWaitableTimer(nil, True, 'WaitableTimer');
  if (hTimer <> 0) then
  begin
     if (SetWaitableTimer(hTimer, FTime, 0, nil, nil, True)) then
     begin
      WaitForSingleObject(hTimer, INFINITE);
   end;
  CloseHandle(hTimer);
  end;


end;

C'était pourtant bien tenté

Merci de vos conseils et aides précieux !





<hr />
L'Armand joue, l'arme en joug... www.art-ment.com

3 réponses

Bacterius Messages postés 3792 Date d'inscription samedi 22 décembre 2007 Statut Membre Dernière intervention 3 juin 2016 10
2 juil. 2009 à 16:39
Mais moi je comprends pas pourquoi tu passes par un WaitForSingleObject ? La fonction SetWaitableTimer attend un pointeur vers un callback, qui sera appelé dès que le timer sera enclenché à l'heure désirée ! Et toi tu envoies "nil" pour le callback ...

Cordialement, Bacterius !
0
Bacterius Messages postés 3792 Date d'inscription samedi 22 décembre 2007 Statut Membre Dernière intervention 3 juin 2016 10
2 juil. 2009 à 16:43
procedure MyCallback(lpArg: Pointer; dwTimerLo: Longword; dwTimerHi: Longword); stdcall;
begin
// Le timer est enclenché, faire divers traitements ...
CloseHandle(hTimer);
end;

hTimer := CreateWaitableTimer(nil, True, 'WaitableTimer');
if hTimer <> 0 then SetWaitableTimer(hTimer, FTime, 0, @MyCallback, nil, True);

Enfin moi c'est comme ça que je conçois l'utilisation de cette fonction au vu de la description MSDN ... mais je n'ai pas testé le code.

Cordialement, Bacterius !
0
L_art_ment Messages postés 302 Date d'inscription vendredi 21 septembre 2007 Statut Membre Dernière intervention 6 février 2013
2 juil. 2009 à 19:03
Salut Bacterius, merci de m'avoir répondu !

Je passe par un WaitForSingleObject car ca y été dans l'exemple que j'ai trouvé, à vrai dire je n'ai passé de temps à comprendre cette fonction mais surtout le SetWaitableTimer...

Et j'arrive enfin mon but !!

Voici le code que j'utilise :

//Ici je detecte toujours les messages de mise hors tension, retour au system...
procedure TForm1.WMPowerBroadcast(var Msg: TMessage);
begin


  //Check for suspend operation
  case Msg.wParam of
     //Query for allowing suspend
     PBT_APMQUERYSUSPEND     :  ;
     //We ARE being suspended (1 seconde = -10000000)
     PBT_APMSUSPEND          :  TWakeupThread.Create('10/06/2009 18:45:00'); //Je passe maintenant en variable la date et l'heure à laquelle je veux relancer mon system
     // Resuming from event, we want monitor display
     PBT_APMRESUMEAUTOMATIC  :  SetThreadExecutionState(ES_DISPLAY_REQUIRED);
     PBT_APMSTANDBY          : ; //TWakeupThread.Create(-200000000);  //detect veille prolongée
  end;


  // Set message result
  Msg.Result:=1;


end;

//La création (HWakeUp est l'heure que j'ai passé en variable quand on a detecté la mise en veille)
constructor TWakeupThread.Create(HWakeUp: string);
begin


  inherited Create(False);
  FreeOnTerminate:=True;
  HeureWakeUp:=HWakeUp;


end;

//Et l'Execute, bon je ne comprend pas toute toute les étapes (comme la manipulation de la date que je lui envoie), mais ca fonctionne..
procedure TWakeupThread.Execute;
var  hTimer:     THandle;
     WakeUpTme: LARGE_INTEGER;
    SysTime : _SystemTime;
    FTime : _FileTime;
    WT,hThread:THandle;
begin
   DateTimeToSystemTime(StrToDateTime(HeureWakeUp), SysTime);
  SystemTimeToFileTime(SysTime, FTime);
  LocalFileTimeToFileTime(FTime, FTime);
  WakeUpTme.LowPart:=FTime.dwLowDateTime;
  WakeUpTme.HighPart:=FTime.dwHighDateTime;
  WT := CreateWaitableTimer(nil,TRUE,'WakeUpThread');
  SetWaitableTimer(WT,WakeUpTme.quadpart,0,nil,nil,true);
  WaitForSingleObject(WT, INFINITE);
  CloseHandle(WT);
end;





<hr />
L'Armand joue, l'arme en joug... www.art-ment.com
0
Rejoignez-nous