[..] Gestion de sortie de boucle

Aide et conseils concernant AutoIt et ses outils.
Règles du forum
.
Répondre
kalixe
Niveau 3
Niveau 3
Messages : 40
Enregistré le : mer. 02 déc. 2009 12:06
Status : Hors ligne

[..] Gestion de sortie de boucle

#1

Message par kalixe »

Bonjour,

J'ai remarqué dans la plupart des appli sur autoit qu'il y a des gros problèmes de sortie de boucle, parfois on se retrouve avec des boucles infinies et on doit alors sortir sauvagemment en tuant le process, donc ma question c'est : est-ce que ce sont des erreurs de programmation ou alors un défaut d'autoit ?

Exemple, j'ai une boucle qui est lancée je veux quitter le programme en cliquant sur l'icone fermer du programme et impossible tant que la boucle n'est pas terminée. Peut-on remédier à cela ? Si oui comment ?
Modifié en dernier par kalixe le lun. 07 déc. 2009 16:51, modifié 2 fois.
Avatar du membre
pop45
Membre émérite
Membre émérite
Messages : 251
Enregistré le : dim. 30 août 2009 16:18
Status : Hors ligne

Re: [..] Gestion de sortie de boucle

#2

Message par pop45 »

Quiter le programme entier : exit

Quitter juste la boucle : exitloop

Et si on peut sortir de la boucle que en "tuant sauvagement" le proces c'est les 2
Cordialement Pop45
Veuillez agrée nos sentiment les plus distinguer, soyez assurer de mon entièr et amical collaboration, bien a vous pour toujours et a jamais dans l'unique but de servir l'espérance de votre satisfaction.
kalixe
Niveau 3
Niveau 3
Messages : 40
Enregistré le : mer. 02 déc. 2009 12:06
Status : Hors ligne

Re: [..] Gestion de sortie de boucle

#3

Message par kalixe »

pop45 a écrit :Quiter le programme entier : exit

Quitter juste la boucle : exitloop

Et si on peut sortir de la boucle que en "tuant sauvagement" le proces c'est les 2
Ca ne marche pas lorsqu'on est dans une boucle, j'ai déjà testé. C'est bien l'objet du problème
Avatar du membre
pop45
Membre émérite
Membre émérite
Messages : 251
Enregistré le : dim. 30 août 2009 16:18
Status : Hors ligne

Re: [..] Gestion de sortie de boucle

#4

Message par pop45 »

exit ou exitloop faut le taper dans le script.......
Cordialement Pop45
Veuillez agrée nos sentiment les plus distinguer, soyez assurer de mon entièr et amical collaboration, bien a vous pour toujours et a jamais dans l'unique but de servir l'espérance de votre satisfaction.
Avatar du membre
Tlem
Site Admin
Site Admin
Messages : 11798
Enregistré le : ven. 20 juil. 2007 21:00
Localisation : Bordeaux
Status : Hors ligne

Re: [..] Gestion de sortie de boucle

#5

Message par Tlem »

En ce qui concerne ce point, la faute n'incombe absolument pas à AutoIt.
C'est au concepteur de prévoir les situations et les possibilités.
Si vous ne rajoutez pas une instruction pour que AutoIt sorte de la boucle lorsque vous faites une action, alors il continue la boucle indéfiniment.
Si vous ne placez pas de pause, alors AutoIt utilise toutes les ressources disponibles et bloque une grande partie de l'utilisation de votre ordinateur.

Le simple fait de rajouter une commande de sortie avec HotKeySet par exemple, suffit à simplifier la sortie du script. Et lorsque vous faites une boucle While dans laquelle il n'y à pas beaucoup d'instruction, prenez l'habitude de rajouter un Sleep afin de libérer des ressources pour le reste des applications de votre ordinateur. ;)
Thierry

Rechercher sur le forum ----- Les règles du forum
Le "ça ne marche pas" est une conséquence commune découlant de beaucoup trop de raisons potentielles ...

Une idée ne peut pas appartenir à quelqu'un. (Albert Jacquard) tiré du documentaire "Copié n'est pas volé".
kalixe
Niveau 3
Niveau 3
Messages : 40
Enregistré le : mer. 02 déc. 2009 12:06
Status : Hors ligne

Re: [..] Gestion de sortie de boucle

#6

Message par kalixe »

Merci,

Mais HotKeySet ça permet de sortir d'une boucle en paramétrant la touche qui va le permettre mais lorsqu'il s'agit d'une sortie par fermeture de la fenêtre ? (la petite croix en haut à droite) comment fait-on ?
Avatar du membre
Tlem
Site Admin
Site Admin
Messages : 11798
Enregistré le : ven. 20 juil. 2007 21:00
Localisation : Bordeaux
Status : Hors ligne

Re: [..] Gestion de sortie de boucle

#7

Message par Tlem »

HotKeySet sert à ce que vous voulez et pas seulement à faire une sortie de boucle. En fait vous attribuez une fonction (qui contient le code que vous voulez) à une touche.

En ce qui concerne la petite croix en haut à droite, il vous faut capturer les événements graphique et agir en fonction.
Pour cela l'exemple de la commande GUICreate suffit largement à comprendre.
Mais au cas ou ...
1 - On crée l'interface graphique grâce à GUICreate puis on ajoute des contrôles (boutons, combo, labels, ...) si c'est nécessaire.
2 - On affiche la GUI terminée grâce à GUISetState(@SW_SHOW).
Si vous oubliez cette ligne, l'interface ne s'affiche pas et donc vous ne pourrez la contrôler. :lol:
3 - Vous devez créer une boucle d'attente afin de ne pas sortir du script, sinon, vous verrez un truc flasher rapidement mais votre script sera terminé aussi vite que vous l'avez lancé...
La boucle doit être du style While/Wend.
Si vous vous en tenez à ça, la GUI sera visible mais aucune de vos actions ne sera interprétées et donc vous devrez terminer le script par le systray ou sauvagement. :mrgreen:
Donc dans votre boucle infinie vous devez 'capturer' les événements graphique et là c'est le rôle de le ligne $msg = GUIGetMsg().
$msg prendra la valeur de l'événement en cours et en l'occurrence lorsque vous cliquez la petite croix en haut à droite, c'est la valeur de $GUI_EVENT_CLOSE qui est retourné.
Donc il suffit de dire que si $msg = $GUI_EVENT_CLOSE, on sort du script : Exit

Voilà, j'espère que mes explications étaient suffisamment claires. ;)
Thierry

Rechercher sur le forum ----- Les règles du forum
Le "ça ne marche pas" est une conséquence commune découlant de beaucoup trop de raisons potentielles ...

Une idée ne peut pas appartenir à quelqu'un. (Albert Jacquard) tiré du documentaire "Copié n'est pas volé".
kalixe
Niveau 3
Niveau 3
Messages : 40
Enregistré le : mer. 02 déc. 2009 12:06
Status : Hors ligne

Re: [..] Gestion de sortie de boucle

#8

Message par kalixe »

C'est parfait, très clair, merci beaucoup pour ces infos clairement présentées, je vais tester tout ça maintenant :wink:
kalixe
Niveau 3
Niveau 3
Messages : 40
Enregistré le : mer. 02 déc. 2009 12:06
Status : Hors ligne

Re: [R] Gestion de sortie de boucle

#9

Message par kalixe »

Et bien finalement non,
Apparemment quand Autoir est dans une boucle il capture pas les events !

exemple :

Code : Tout sélectionner

#include <ButtonConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

Global $Cpt1

Local $Montableau[10]

$Montableau[0] = "lundi"
$Montableau[1] = "mardi"
$Montableau[2] = "mercredi"
$Montableau[3] = "jeudi"
$Montableau[4] = "vendredi"
$Montableau[5] = "samedi"
$Montableau[6] = "dimanche"
$Montableau[7] = "voila"
$Montableau[8] = "c'est"
$Montableau[9] = "Fini"

#Region ### START Koda GUI section ### Form=
$Form1 = GUICreate("Form1",682, 215, 192, 124)
$Edit1 = GUICtrlCreateEdit("", 16, 8, 200, 130)
$Edit2 = GUICtrlCreateEdit("", 240, 8, 200, 130)
$Edit3 = GUICtrlCreateEdit("", 456, 8, 200, 130)
$Button1 = GUICtrlCreateButton("Lancer", 184, 152, 89, 41, $WS_GROUP)
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $Button1
            Compteur()
    EndSwitch
WEnd

Func Compteur()
    For $Cpt1 = 0 to 9 Step 1
        $msg = GUIGetMsg()
        if $msg = $GUI_EVENT_CLOSE then
            Exit
        else
            GUICtrlSetData($Edit1, $Cpt1) ; on réecrit par dessus
            GUICtrlSetData($Edit2, $Cpt1 & @CRLF, 1) ; on ecrit sur le ligne du dessous
            GUICtrlSetData($Edit3,"ligne1 : sa bouge pas" & @CRLF & "ligne2 : " &  $Cpt1 & @CRLF & "ligne3 : " & $Montableau[$Cpt1] ) ; on ecrit a la ligne 2
            Sleep(500)
        EndIf
    Next
EndFunc

 
Avatar du membre
Tlem
Site Admin
Site Admin
Messages : 11798
Enregistré le : ven. 20 juil. 2007 21:00
Localisation : Bordeaux
Status : Hors ligne

Re: [..] Gestion de sortie de boucle

#10

Message par Tlem »

Le problème dans votre cas, c'est que la capture de l'événement à très peut de chance d'arriver. :roll:
Imaginez bien que votre PC travail extrêmement vite. Donc dans la boucle For de la fonction Compteur(), sachez que entre le moment ou il incrémente $Cpt1 et le moment ou il arrive à la pause de 500ms, le temps d'exécution n'aura vraisemblablement pas excédé 2 à 3 ms ... :roll:
Ce qui laisse peut de temps au script pour réagir. :lol:

A ce stade, à première vue il n'y à pas grand chose de possible, puisque AutoIt n'est pas multitâche.
Cela dit certaines choses peuvent être détournées ou adaptées à nos besoin ... :roll:

Donc ce qu'il vous faudrait, c'est plus de temps pour capturer l'événement de la GUI. Et bien donnez lui du temps. :wink:
► Afficher le texte
C'est peu orthodoxe, mais ça fonctionne.
Sinon il faut passer par la fonction AdlibEnable() et gérer les variables globalement, mais ce sera sûrement bien plus complexe que cette astuce.

Comme je l'ai déjà dit : C'est au concepteur de prévoir les situations et les possibilités. :wink:
Thierry

Rechercher sur le forum ----- Les règles du forum
Le "ça ne marche pas" est une conséquence commune découlant de beaucoup trop de raisons potentielles ...

Une idée ne peut pas appartenir à quelqu'un. (Albert Jacquard) tiré du documentaire "Copié n'est pas volé".
LaBbTAc
Niveau 1
Niveau 1
Messages : 2
Enregistré le : mar. 28 déc. 2010 18:18
Status : Hors ligne

Re: [..] Gestion de sortie de boucle

#11

Message par LaBbTAc »

Bonsoir, ce post est très vieux mais comme c'est ici que je suis tombé en me posant la même question, et que je me posais cette question régulièrement depuis des années que je bidouille en au3, je donne ici mes petites solutions que je viens de tester. Effectivement, sauf erreur, il n'est pas possible d'intervenir sur un script qui exécute une boucle, sauf en faisant une pause "d'attente d'ordre" comme l'a montré Tlem, ou en faisant un process " *.exe " à part, sur lequel on agit sauvagement par un ProcessClose. Je faisais comme ça jusqu'à maintenant.
En ce qui me concerne je cherchais surtout à sortir de la boucle sans sortir du script.
La Hotkey est très efficace, on l'utilise en général en sortie d'urgence. En mode graphique il faut que le focus soit sur la Gui pour que cela fonctionne. On peut utiliser la Hotkey pour sortir d'une boucle, en passant par une variable booléenne. Car il est interdit d'écrire un ExitLoop à l'extérieur de la boucle concernée.
Par ailleurs j'ai repris aussi l'idée de la petite boucle d'attente d'ordre, en la modifiant pour qu'elle permette de sortir de la boucle à fermer sans fermer le script en cours.

En ce moment je fais joujou avec mon port parallèle et des leds... donc j'ai besoin de sortir de mes boucles.

Cordialement - Christophe

----------------------------------------------------------------------------------
OrdreUserSortieBoucle_PourForum-01.au3
(2.26 Kio) Téléchargé 98 fois
#include <GUIConstantsEx.au3>

   #cs ---------------------------------------------------------------------------------------------------------------------------------------------
        Deux moyens pratiques pour sortir d'une boucle infinie sans devoir crasher un process. Nous savons qu'il est impossible d'écrire un ExitLoop
        à l'extérieur de la boucle concernée, ce qui oblige à écrire les routines dans chaque boucle (on ne peut pas faire de fonction)

        1) Hotkey : je passe par une petite fonction qui inverse une variable booléenne qui sera testée dans le boucle
        2) Sous-boucle "d'atttente d'ordre" proposée par Tlem du Forum Autoit Français;  mise à ma sauce.

    #ce ----------------------------------------------------------------------------------------------------------------------------------------------

    ; <---- sortie de boucle par le bouton Echap (fonction _ExitLoop)
    $exitLoop = 0
    HotKeySet("{ESC}", "_ExitLoop")
    ;------------------------------->

    $gui = GUICreate(" Sortie boucle ordonnée - essai", 300, 80)
    $A_button = GUICtrlCreateButton("Boucle", 5,30, 40)
    $B_button = GUICtrlCreateButton("Stop", 45, 30, 30)
    GUISetBkColor(0xCC0066)
    GUISetState(@SW_SHOW)


    While 1; loop waiting for tray messages
        $msgG = GUIGetMsg()
        Select
            Case $msgG = $GUI_EVENT_CLOSE ; sortie fermeture
                ExitLoop
            Case    $msgG =$A_button
                Boucle()
        EndSelect

    Wend

    Func Boucle()
        Local $ForExitLoop = 0
        Local $compt = 0

        While 1
            For $i = 1 To 100
                If GUIGetMsg() = $B_button then
                    ConsoleWrite("Exit Loop B !"&@CRLF)
                    $ForExitLoop = 1
                    ExitLoop
            ElseIf GUIGetMsg()= $GUI_EVENT_CLOSE Then
               Exit
                EndIF
            Next

            If  $ForExitLoop =1 Then
                ConsoleWrite(">>>> Exit Loop A ! Le script revient en attente ....."&@CRLF)
                ExitLoop
            EndIf

            ConsoleWrite("Loop "&$compt&@CRLF)
            Sleep(500)
            $compt +=1
        Wend
    EndFunc

    Func _ExitLoop() ; Pour Hotkey
        $exitLoop = 1
    EndFunc
LaBbTAc
Niveau 1
Niveau 1
Messages : 2
Enregistré le : mar. 28 déc. 2010 18:18
Status : Hors ligne

P.S. et Erratum

#12

Message par LaBbTAc »

En fait, la boucle intérieure d'attente d'ordre, même raccourcie à 50, perturbe beaucoup le timing dans la boucle qui devient très aléatoire, et, bizarrement, elle très perturbée par les mouvement de souris (!!!). En tout cas c'est inutilisable quand le timing est important, ce qui est le cas dans mon projet : mes leds doivent clignoter en rythme !
Donc la hotkey améliorée reste la meilleure solution je crois.

C'est peut-être là aussi qu'on touche les limite du basic... Mais j'ai la flemme de me mettre à autre chose, c'est le début de la vieillesse.

Cordialement - Christophe
Avatar du membre
jchd
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 2282
Enregistré le : lun. 30 mars 2009 22:57
Localisation : Sud-Ouest de la France (43.622788,-1.260864)
Status : Hors ligne

Re: [..] Gestion de sortie de boucle

#13

Message par jchd »

Il y a deux solutions à ce faux problème. Soit on replace la gestion de tous les messages dans une seule et unique boucle (en ne réalisant que des actions rapides pour chaque message), soit on passe en mode évènementiel. Dans les deux cas il faut gérer correctement les conditions de réalisation des actions, soit suite à message, soit dans la boucle de processus.

Le langage utilisé n'a absolument rien à voir avec la question initiale et ça serait le même tas de spaghettis en C ou en Python si on conserve la même structure avec des GetMsg dans tous les coins de boucles imbriquées qui ne traitent qu'une partie des messages utiles, qui est exactement l'inverse de la philosophie de Windows et des autres interfaces graphiques à pompe de messages.
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
Avatar du membre
mikell
Spammer !
Spammer !
Messages : 6292
Enregistré le : dim. 29 mai 2011 17:32
Localisation : Deep Cévennes
Status : Hors ligne

Re: [..] Gestion de sortie de boucle

#14

Message par mikell »

@LaBbTAc

Tout dépend de ce qu'on entend par sortie de boucle. Le sujet initial parle de fermer une fenêtre ou par un bouton (post #1) ou par la croix de la fenêtre (post #6) alors qu'une boucle est en cours d'exécution. Pour ça en plus de la hotkey de Tlem ou du mode événementiel suggéré par jc il y a aussi GUIRegisterMsg
Voilà un exemple qui reprend en gros ton script

Code : Tout sélectionner

GUICreate("My GUI") 
$label = GUICtrlCreateLabel("", 30, 30, 30, 30) 
$btn = GuiCtrlCreateButton("Roule", 10, 60, 60, 25)
$exit = GuiCtrlCreateButton("Exit", 20, 90, 60, 25)
GUISetState()     

GUIRegisterMsg(0x0112, "_bye_1")  ; 0x0112 = $WM_SYSCOMMAND
GUIRegisterMsg(0x0111, "_bye_2")   ; 0x0111 = $WM_COMMAND

While 1
$msg = GUIGetMsg()
Switch $msg
	Case -3    ; -3 = $GUI_EVENT_CLOSE
		 Exit   
	Case $btn 
		_roule()
EndSwitch
Wend

Func _roule()
  For $i = 1 to 100
	GuictrlSetdata($label, $i)
	Sleep(500)
  Next
EndFunc
  
Func _bye_1($hWnd, $Msg, $wParam, $lParam)
    If BitAND($wParam, 0xFFF0) = 0xF060 Then Exit   ; 0xF060 = $SC_CLOSE
EndFunc

Func _bye_2($hWnd, $Msg, $wParam, $lParam) 
    If BitAND($wParam, 0x0000FFFF) =  $exit Then Exit
EndFunc  

" L'échec est le fondement de la réussite. " (Lao-Tseu )
" Plus ça rate, plus on a de chances que ça marche " (les Shadoks )
Avatar du membre
jchd
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 2282
Enregistré le : lun. 30 mars 2009 22:57
Localisation : Sud-Ouest de la France (43.622788,-1.260864)
Status : Hors ligne

Re: [..] Gestion de sortie de boucle

#15

Message par jchd »

Oui, ça ou encore plus simplement gérer aussi l'exit en testant $GUI_EVENT_CLOSE dans la boucle interne, mais en comprenant bien que faire un sleep(500) dans une boucle de gestion de messages revient à créer une appli qui ne se comporte pas de façon fluide.
Mais avoir plusieurs boucles imbriquées où l'on intercepte un même message en plusieurs endroits n'est pas la structure de code la plus simple ni la plus facile à faire évoluer.
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
Avatar du membre
mikell
Spammer !
Spammer !
Messages : 6292
Enregistré le : dim. 29 mai 2011 17:32
Localisation : Deep Cévennes
Status : Hors ligne

Re: [..] Gestion de sortie de boucle

#16

Message par mikell »

Oui c'était l'idée de mon post (éviter au maximum et autant que possible les boucles imbriquées avec surveillance de messages)
Si le Sleep(500) évoqué est celui de mon code, il n'est là que pour rendre l'affichage dans la label plus lisible et peut très bien être supprimé sans autre incidence sur le fonctionnement global du truc
" L'échec est le fondement de la réussite. " (Lao-Tseu )
" Plus ça rate, plus on a de chances que ça marche " (les Shadoks )
Répondre