OVH Cloud OVH Cloud

VB/DoEvents C++ ?

33 réponses
Avatar
PurL
Bonjour,

Dans un programme C++ en mode console (fonction main) je dois lancer un
timer (SetTimer) et rien d'autre. Mais il ne faut pas que je sorte du main.
Venant du monde VB, je ferais en VB :

bOK = false
hTimer = SetTimer(0, 0, delay, TimerProc)
While(not bOK) if GetInputState Then DoEvents 'pour pas bloquer
KillTimer hTimer


Sachant que c'est la procédure TimerProc qui mettera à true bOK et donc
mettra fin au programme.
En C++ le programme est quasiment le meme, sauf que je ne sais pas
reproduire le comportement de la ligne :
"if GetInputState then DoEvents"

Comment faire ?

Merci,

PurL

10 réponses

1 2 3 4
Avatar
Manuel Leclerc
PurL a écrit :

Dans un programme C++ en mode console (fonction main)
je dois lancer un timer (SetTimer) et rien d'autre. Mais
il ne faut pas que je sorte du main. Venant du monde VB,
je ferais en VB :

bOK = false
hTimer = SetTimer(0, 0, delay, TimerProc)
While(not bOK) if GetInputState Then DoEvents
KillTimer hTimer

Sachant que c'est la procédure TimerProc qui mettera à
true bOK et donc mettra fin au programme.
En C++ le programme est quasiment le meme, sauf que je
ne sais pas reproduire le comportement de la ligne :
"if GetInputState then DoEvents"

Comment faire ?



MSG msg;
BOOL bRet;
while( ( bRet = GetMessage( &msg, NULL, 0, 0 ) ) != 0 ) {
if (bRet != -1) {
DispatchMessage(&msg);
} // endif
} // end while

La documentation est un peu floue, mais il semble que
la fonction "DispatchMessage" sache reconnaître un
message WM_TIMER avec un HWND NULL et une TIMERPROC
valorisée et que ce soit alors elle qui appelle la
procédure. Il n'y a alors pas de passage par une
window procedure classique, c'est totomatique.

Essayes et dis moi si ça marche, ça m'intéresse.

Si ça marche, pour mettre fin au programme, ta
TimerProc pourrait utiliser PostQuitMessage (au
lieu de ton bOK ) ce qui fera rendre un code retour
nul au GetMessage, et provoquera la sortie de la
boucle
Avatar
Møgluglu
PurL a écrit:
Dans un programme C++ en mode console (fonction main) je dois lancer
un timer (SetTimer) et rien d'autre. Mais il ne faut pas que je sorte
du main.
[...]
Comment faire ?



Le mieux est d'utiliser un event. Tu appelles CreateEvent avec
bInitialState suf FALSE, puis tu l'attends avec WaitForSingleObject.
Et la procédure TimerProc appelle SetEvent au lieu de mettre bOK à true.

--
Møgluglu
Avatar
Manuel Leclerc
Møgluglu a écrit :

PurL a écrit:

> Dans un programme C++ en mode console (fonction main)
> je dois lancer un timer (SetTimer) et rien d'autre. Mais
> il ne faut pas que je sorte du main.
> [...]
> Comment faire ?

Le mieux est d'utiliser un event. Tu appelles CreateEvent
avec bInitialState suf FALSE, puis tu l'attends avec
WaitForSingleObject. Et la procédure TimerProc appelle SetEvent
au lieu de mettre bOK à true.



Heu... Et qui va appeler la procédure TimerProc toutes les
x milli-secondes ?

Ca me fait penser que l'OP pourrait tout aussi bien
faire en C:

while ( bOK ) {
Sleep( x );
TimerProc();
} // end while

Finalement, l'intérêt des Timer, c'est quand ON A une boucle
de dispatching et qu'on ne peut donc pas faire while() sleep.

Mais quand on n'a PAS de boucle de dispatching, pourquoi
s'embêter avec ?
Avatar
PurL
> La documentation est un peu floue, mais il semble que
la fonction "DispatchMessage" sache reconnaître un
message WM_TIMER avec un HWND NULL et une TIMERPROC
valorisée et que ce soit alors elle qui appelle la
procédure. Il n'y a alors pas de passage par une
window procedure classique, c'est totomatique.

Essayes et dis moi si ça marche, ça m'intéresse.

Si ça marche, pour mettre fin au programme, ta
TimerProc pourrait utiliser PostQuitMessage (au
lieu de ton bOK ) ce qui fera rendre un code retour
nul au GetMessage, et provoquera la sortie de la
boucle



Ca marche impec, et, effectivement PostQuitMessage nous sort de la boucle.

Merci pour ton aide,

PurL
Avatar
PurL
> Ca me fait penser que l'OP pourrait tout aussi bien
faire en C:

while ( bOK ) {
Sleep( x );
TimerProc();
} // end while



Effectivement, c'est plus clair et simple.
Mais la fonction Sleep permet-elle d'avoir une fréquence (précision) aussi
bonne que SetTimer ?

PurL
Avatar
Manuel Leclerc
PurL a écrit :

> Ca me fait penser que l'OP pourrait tout aussi bien
> faire en C:
>
> while ( bOK ) {
> Sleep( x );
> TimerProc();
> } // end while

Effectivement, c'est plus clair et simple.
Mais la fonction Sleep permet-elle d'avoir une
fréquence (précision) aussi bonne que SetTimer ?



Je ne crois pas que l'on puisse dire que SetTimer
soit d'une précision particulièrement géniale. En
tout cas, quand il est utilisé dans une application
graphique qui fait aussi d'autres choses, et dans
le contexte d'un PC un peu chargé en autres processus,
la fréquence effective à laquelle la fonction TimerProc
sera appelée me semble TRES variable. Si ça te chagrine,
tu peux essayer de faire des tests comparatifs. Une
troisième solution pourrait être d'utiliser les objets
systèmes "waitable timer".
http://www.google.fr/search?q=msdn+waitable+timer
Je ne sais pas si on peut en attendre une meilleure
précision, surtout dans le cas simple de ta fonction
main. C'est indiscret de te demander ce que tu fais
dans TimerProc et à quelle fréquence ?
Avatar
PurL
> troisième solution pourrait être d'utiliser les objets
systèmes "waitable timer".
http://www.google.fr/search?q=msdn+waitable+timer



Je vais yeuter ça pour un autre probleme, ca pourrait me servir, merci

Je ne sais pas si on peut en attendre une meilleure
précision, surtout dans le cas simple de ta fonction
main. C'est indiscret de te demander ce que tu fais
dans TimerProc et à quelle fréquence ?



Non pas indiscret mais je pense sans intéret :

Mon programme doit exploiter les fichiers d'un autre programme tous les
jours à minuit (déclencher par le gestionnaire des taches). Or il arrive que
certains fichiers sont inaccessibles pour des raisons que j'ignore encore.
Donc le programme se lance, effectue son traitement et s'il détecte un
probleme, il se regle pour refaire le traitement une 10zaine de fois toutes
les minutes (je te l'accorde que dans ce cas, la précision ou s'en fout un
peu mais j'ai d'autres prog qu'utilisent des SetTimer alors je m'informe)

Merci pour votre aide,

PurL
Avatar
Ambassadeur Kosh
ça me dérange ta boucle while(!bOk).
c'est de l'attente active.
c'est pourri et inutile.

un timer a pour but de poster un message à une frequence precise.
toutes les secondes par exemple. donc toutes les secondes, ton appli va
recevoir un message ou déclencher la procedure associée au tick timer.

mais la tu scrutes en permanence si ton flag a bougé. ton programme tourne
et pompe du temps à faire "l'action de dormir". si tu utilises le Timer,
tant qu'il n'y aura pas de message, le programme ne fera rien. cad que le
systeme ne pretera pas le CPU a ce programme parcequ'il sait qu'il est
bloqué en attendant quelque chose qu'il doit lui donner. c'est l'interet du
WaitForSingleObject et de tout ça. apres, traiter par message ou par threads
avec des rendez vous et de la synchros, c'est toi qui voit.

un processus, c'est pas seulement des données et du code. pour le systeme,
il y'a un marqueur d'état "j'attend une donnée/je travaille/...", sans
compter la priorité etc etc...

voila voila
Avatar
Manuel Leclerc
PurL a écrit :

Mon programme doit exploiter les fichiers d'un autre
programme tous les jours à minuit (déclencher par le
gestionnaire des taches). Or il arrive que certains
fichiers sont inaccessibles pour des raisons que
j'ignore encore.



Je pense que la première chose à faire est de
récupérer la code retour de l'erreur d'ouverture des
fichiers :-) C'est quelle valeur ?

Donc le programme se lance, effectue son traitement
et s'il détecte un probleme, il se regle pour refaire
le traitement une 10zaine de fois toutes les minutes
(je te l'accorde que dans ce cas, la précision ou s'en
fout un peu mais j'ai d'autres prog qu'utilisent des
SetTimer alors je m'informe)



Il y a une différence de sémantique importante. Avec
SetTimer ta fonction sera appelée en moyenne le bon
nombre de fois (10 fois par minutes) mais peut être
qu'il y aura une fois un intervalle de 12 secondes (au
lieu de 6), si ta machine est VRAIMENT sous-dimensionnée
et à genou, suivi d'un intervalle de 0 secondes.
Les messages WM_TIMER sont postés dans la queue à peu
prêt régulièrement, mais si personne ne les dépile,
ils s'accumulent.

Avec Sleep tu peux évidement avoir le problème des 12
secondes mais je ne vois pas comment tu pourrais avoir
celui des 0 secondes :-)

Tout ça est un peu théorique et ne doit être significatif
qu'avec des valeurs d'intervalle beaucoup plus petites que
6 secondes et une machine à la rue.

OU SI ta fonction TimerProc prends plus de 6 secondes à
s'exécuter :-)
Avatar
PurL
Ambassadeur Kosh wrote:
ça me dérange ta boucle while(!bOk).
c'est de l'attente active.
c'est pourri et inutile.



donc tu préconises la méthode de Møgluglu ?

si tu utilises
le Timer, tant qu'il n'y aura pas de message, le programme ne fera
rien.



Bah il se terminera !
Puisque je ne suis pas dans une appli fenetrée mais de type console.

voila voila



Merci,

PurL.
1 2 3 4