Jump to content

ExitLoop? How to break out of loop?


Anne
 Share

Recommended Posts

Hi scripters.
 
I have been working on a little tool but then I ran into a problem.
I have found a way to stop a loop/pause the script with the click of a button. However, the loop will continue until the end of the loop before stopping.
This is the script which pauses after the loop has ended:
 

#include <GUIConstantsEx.au3>

#Region ### START Koda GUI section ### Form=
Opt("GUIOnEventMode", 1)
$doit = False
$Form1 = GUICreate("Pause Toggle Project", 470, 65, 351, 254)
$Button1 = GUICtrlCreateButton("START / PAUSE", 8, 16, 129, 33)
$Button2 = GUICtrlCreateButton("EXIT PROGRNAM", 310, 16, 129, 33)
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###
GUICtrlSetOnEvent($Button1, "TogglePause")
GUICtrlSetOnEvent($Button2, "Terminate")
GUISetOnEvent($GUI_EVENT_CLOSE, "Close")

GUISetState()

While 1
Sleep(100)
If $doit Then
$i = 0
Do

ConsoleWrite(123 & @CRLF)
Sleep(1000)
ConsoleWrite(456 & @CRLF)
Sleep(1000)
ConsoleWrite(789 & @CRLF)
Sleep(1000)
ConsoleWrite("abc" & @CRLF)
Sleep(1000)
ConsoleWrite("def" & @CRLF)
Sleep(1000)
ConsoleWrite("ghi" & @CRLF)
Sleep(1000)

Until $i = 100 Or $doit = False
ToolTip('Stopping Loop...')
Sleep(1500)
$doit = False
ToolTip('')
EndIf
WEnd


Func TogglePause()
$doit = Not $doit
EndFunc

Func Close()
Exit
EndFunc ;==>CancelPressed

Func Terminate()
Exit 0
EndFunc ;==>Terminate

Now, I was wondering if it could be possible to stop the DO loop immediately. So that it breaks out of the loop when you click a button (call the function).
I have tried a little with ExitLoop. However, I have hit an impassable wall.

I added a new function called "Abort()". Calling this will break out of the DO loop and execute the code after UNTIL.
However, this also breaks the script so that no buttons will work. I believe the GUICtrlSetOnEvent stops working.
Is it possible to use the ExitLoop within the Abort() function without breaking my script?

Or am I approaching this entirely wrong?

The following code is the same as the above, but with the Abort() function:

#include <GUIConstantsEx.au3>

#Region ### START Koda GUI section ### Form=
Opt("GUIOnEventMode", 1)
$doit = False
$Form1 = GUICreate("Pause Toggle Project", 470, 65, 351, 254)
$Button1 = GUICtrlCreateButton("START / PAUSE", 8, 16, 129, 33)
$Button2 = GUICtrlCreateButton("EXIT PROGRNAM", 310, 16, 129, 33)
$Button3 = GUICtrlCreateButton("ABORT LOOP NOW", 160, 16, 129, 33)
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###
GUICtrlSetOnEvent($Button1, "TogglePause")
GUICtrlSetOnEvent($Button2, "Terminate")
GUICtrlSetOnEvent($Button3, "Abort")
GUISetOnEvent($GUI_EVENT_CLOSE, "Close")

GUISetState()

While 1
Sleep(100)
If $doit Then
$i = 0
Do

ConsoleWrite(123 & @CRLF)
Sleep(1000)
ConsoleWrite(456 & @CRLF)
Sleep(1000)
ConsoleWrite(789 & @CRLF)
Sleep(1000)
ConsoleWrite("abc" & @CRLF)
Sleep(1000)
ConsoleWrite("def" & @CRLF)
Sleep(1000)
ConsoleWrite("ghi" & @CRLF)
Sleep(1000)

Until $i = 100 Or $doit = False
ToolTip('Stopping Loop...')
Sleep(1500)
$doit = False
ToolTip('')
EndIf
WEnd


Func TogglePause()
$doit = Not $doit
EndFunc

Func Close()
Exit
EndFunc ;==>CancelPressed

Func Terminate()
Exit 0
EndFunc ;==>Terminate

Func Abort()
    If $doit = False Then
        $doit = Not $doit
    ElseIf $doit = True Then
        $doit = Not $Doit
        While 1
            ExitLoop 2
        WEnd
    EndIf
EndFunc
Link to comment
Share on other sites

Hi,

use HotKeySet

look the FAQ

saludos

Edited by Danyfirex
Link to comment
Share on other sites

There is a great tutorial about Interrupting a Running Function in the wiki:

http://www.autoitscript.com/wiki/Interrupting_a_running_function

Read through it and try to understand the code in the examples. I haven't looked at your code, but ExitLoop() will get you out of a loop.

Edited by czardas
Link to comment
Share on other sites

CODE DELETED (it was not a good example)

;

Now the method shown may not be suitable depending on what your program is ultimately going to do. It is important to look at the examples I linked to earlier where the code is using well tested and standard methods. Next to try a different approach.

Edited by czardas
Link to comment
Share on other sites

Same idea as above but a lot neater. The above code is an example of bad coding practice.

;

#include <GUIConstantsEx.au3>

#Region ### START Koda GUI section ### Form=
Opt("GUIOnEventMode", 1)
$doit = False
$Form1 = GUICreate("Pause Toggle Project", 470, 65, 351, 254)
$Button1 = GUICtrlCreateButton("START / PAUSE", 8, 16, 129, 33)
$Button2 = GUICtrlCreateButton("EXIT PROGRNAM", 310, 16, 129, 33)
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###
GUICtrlSetOnEvent($Button1, "TogglePause")
GUICtrlSetOnEvent($Button2, "Close") ; Changed
GUISetOnEvent($GUI_EVENT_CLOSE, "Close")

GUISetState()

Local $aData[6] = [123, 456, 789, "abc", "def", "ghi"] ; This array stores the text we want to send.
Local  $iCount1 = 0, $iCount2 = 0

While 1
    Sleep(100)
    If $doit Then
        $iCount2 = 0 ; Reset or it will stop running.
        While 1
            If $doit = False Or $iCount2 = 100 Then ExitLoop
            ConsoleWrite($aData[$iCount1] & @CRLF)
            Sleep(1000)
            $iCount1 = Mod($iCount1 + 1, 6)
            $iCount2 += 1
        WEnd
        ToolTip('Stopping Loop...')
        Sleep(1500)
        $doit = False
        ToolTip('')
    EndIf
WEnd

Func TogglePause()
    $doit = Not $doit
EndFunc

Func Close()
    Exit
EndFunc ;==>CancelPressed

;

Ultimately you are going to have to get used to other methods.

Edited by czardas
Link to comment
Share on other sites

Hi,

use HotKeySet

look the FAQ

saludos

 

HotKeySet will do me no good because I need it to be a button which stops the loop.

However, HotKeySet do stop the loop when the following function is called with a hotkey:

Func MyExit()

    $doit = Not $Doit

        While 1

            ExitLoop 2

        WEnd

EndFunc

Any particular reason it works with HotKeySet and not when the function is called by other means?

The method you are using is not ideal. Here is a modification to your first post which solves the problem but still using your method. This can be done better, but I am posting the example so hopefully you will get an idea why your original code is broken.

;

#include <GUIConstantsEx.au3>

#Region ### START Koda GUI section ### Form=
Opt("GUIOnEventMode", 1)
$doit = False
$Form1 = GUICreate("Pause Toggle Project", 470, 65, 351, 254)
$Button1 = GUICtrlCreateButton("START / PAUSE", 8, 16, 129, 33)
$Button2 = GUICtrlCreateButton("EXIT PROGRNAM", 310, 16, 129, 33)
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###
GUICtrlSetOnEvent($Button1, "TogglePause")
GUICtrlSetOnEvent($Button2, "Close") ; Changed
GUISetOnEvent($GUI_EVENT_CLOSE, "Close")

GUISetState()

Local $aData[6] = [123, 456, 789, "abc", "def", "ghi"] ; This array stores the text we want to send.
Local $iCount
Local $i = 0

While 1
    Sleep(100)
    If $doit Then
        $iCount = 0
        While 1
            For $i = $i To 5
                If $i = -1 Then $i = 0
                If $doit = False Or $iCount = 100 Then ExitLoop ; Test after every command
                ConsoleWrite($aData[$i] & @CRLF)
                $iCount += 1 ; Increment the count
                Sleep(1000)
                If $i = 5 Then $i = -1 ; This will become 0 again on the next loop
            Next

            ;ConsoleWrite(123 & @CRLF)
            ;Sleep(1000)
            ;ConsoleWrite(456 & @CRLF)
            ;Sleep(1000)
            ;ConsoleWrite(789 & @CRLF)
            ;Sleep(1000)
            ;ConsoleWrite("abc" & @CRLF)
            ;Sleep(1000)
            ;ConsoleWrite("def" & @CRLF)
            ;Sleep(1000)
            ;ConsoleWrite("ghi" & @CRLF)
            ;Sleep(1000)
        WEnd
        

        ToolTip('Stopping Loop...')
        Sleep(1500)
        $doit = False
        ToolTip('')
    EndIf
WEnd


Func TogglePause()
    $doit = Not $doit
EndFunc

Func Close()
    Exit
EndFunc ;==>CancelPressed

;Func Terminate()
;    Exit 0
;EndFunc ;==>Terminate

;

Now the method shown may not be suitable depending on what your program is ultimately going to do. It is important to look at the examples I linked to earlier where the code is using well tested and standard methods. Next to try a different approach.

 

I see the logic in using Arrays. But it will only work for certain things.

Consider if I wanted the loop to contain several MsgBox and other functions.

However, I will try to look at the link you brought in the earlier post.

And thank you both for replying.

Link to comment
Share on other sites

Arrays are not always suitable and there is no best answer for every situation. You have a count up to 100. That won't always be there. I assumed you wanted the pattern to pause and not reset again to the beginning. All of what you are looping through can be done in a function and perhaps interrupted using one of several different methods. I linked you the tutorial.

Edited by czardas
Link to comment
Share on other sites

Arrays are not always suitable and there is no best answer for every situation. You have a count up to 100. That won't always be there. I assumed you wanted the pattern to pause and not reset again to the beginning. All of what you are looping through can be done in a function and perhaps interrupted using one of several different methods. I linked you the tutorial.

 

Yea I gave it a read while you replied. I must say, brilliant tutorial!

It gave me at least two ideas but I think I'll go with the flag strategy.

Something like this:

#include <GUIConstantsEx.au3>

#Region ### START Koda GUI section ### Form=
Opt("GUIOnEventMode", 1)
$doit = False
$Form1 = GUICreate("Pause Toggle Project", 470, 65, 351, 254)
$Button1 = GUICtrlCreateButton("START / PAUSE", 8, 16, 129, 33)
$Button2 = GUICtrlCreateButton("EXIT PROGRNAM", 310, 16, 129, 33)
$Button3 = GUICtrlCreateButton("ABORT LOOP NOW", 160, 16, 129, 33)
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###
GUICtrlSetOnEvent($Button1, "TogglePause")
GUICtrlSetOnEvent($Button2, "Terminate")
GUICtrlSetOnEvent($Button3, "Abort")
GUISetOnEvent($GUI_EVENT_CLOSE, "Close")

GUISetState()
$Abort = False

While 1
Sleep(100)
If $doit Then
$i = 0
Do

ConsoleWrite(123 & @CRLF)
Sleep(100)
If $Abort = True Then
    $Abort = False
    ExitLoop
EndIf
ConsoleWrite(456 & @CRLF)
Sleep(100)
If $Abort = True Then
    $Abort = False
    ExitLoop
EndIf
ConsoleWrite(789 & @CRLF)
Sleep(100)
If $Abort = True Then
    $Abort = False
    ExitLoop
EndIf
ConsoleWrite("abc" & @CRLF)
Sleep(100)
If $Abort = True Then
    $Abort = False
    ExitLoop
EndIf
ConsoleWrite("def" & @CRLF)
Sleep(100)
If $Abort = True Then
    $Abort = False
    ExitLoop
EndIf
ConsoleWrite("ghi" & @CRLF)
Sleep(100)

Until $i = 100 Or $doit = False
ToolTip('Stopping Loop...')
Sleep(1500)
$doit = False
ToolTip('')
EndIf
WEnd


Func TogglePause()
$doit = Not $doit
EndFunc

Func Close()
Exit
EndFunc ;==>CancelPressed

Func Terminate()
Exit 0
EndFunc ;==>Terminate

Func Abort()
        $Abort = True
EndFunc

I'll just have to place the flag at multiple occasions like in the example above. To be honest, I had considered this idea myself as a last resort. I just think it's a horrible or broken solution. But I suppose that's the price you pay for using a single threaded language.

Thank you, I'll consider this case solved.

Link to comment
Share on other sites

I'm glad you read it, and sorry my code was a bit rushed before. It looked worse after I added a line because I overlooked a detaill. Anyway Melba23 is responsible for that tutorial which helped me a lot I must say. :)

Now I just looked at your code. There's still some things wrong. $i will never be 100 because you don't increment it anywhere in the loop. You must add $i += 1 somewhere.

Edited by czardas
Link to comment
Share on other sites

Now you can interrupt your process, you can also encapsulate repeated actions inside a function. I created a function _WooHoo() for this, which replaces the duplicated code.

;

#include <GUIConstantsEx.au3>

#Region ### START Koda GUI section ### Form=
Opt("GUIOnEventMode", 1)
Global $doit = False
Global $Form1 = GUICreate("Pause Toggle Project", 470, 65, 351, 254)
Global $Button1 = GUICtrlCreateButton("START / PAUSE", 8, 16, 129, 33)
Global $Button2 = GUICtrlCreateButton("EXIT PROGRNAM", 310, 16, 129, 33)
Global $Button3 = GUICtrlCreateButton("ABORT LOOP NOW", 160, 16, 129, 33)
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###
GUICtrlSetOnEvent($Button1, "TogglePause")
GUICtrlSetOnEvent($Button2, "Close") ; Changed again
GUICtrlSetOnEvent($Button3, "Abort")
GUISetOnEvent($GUI_EVENT_CLOSE, "Close")

GUISetState()
Global $Abort = False

While 1
    Sleep(100)
    If $doit Then
        $Abort = False
        $i = 0 ; This needs some work
        Do
            If _WooHoo(123) Then ExitLoop
            If _WooHoo(456) Then ExitLoop
            If _WooHoo(789) Then ExitLoop
            If _WooHoo("abc") Then ExitLoop
            If _WooHoo("def") Then ExitLoop
            If _WooHoo("ghi") Then ExitLoop
            $i += 1
        Until $i = 100 Or $doit = False
    ToolTip('Stopping Loop...')
    Sleep(1500)
    $doit = False
    ToolTip('')
    EndIf
WEnd

Func _WooHoo($vInfo)
    ConsoleWrite($vInfo & @CRLF)
    Sleep(100)
    Return $Abort
EndFunc

Func TogglePause()
    $doit = Not $doit
EndFunc

Func Close()
    Exit
EndFunc ;==>CancelPressed

;Func Terminate()
;   Exit 0
;EndFunc ;==>Terminate

Func Abort()
    $Abort = True
EndFunc

;

or maybe something like this alternative.

Func _WooHoo($vInfo)
    If $Abort Then Return True
    ConsoleWrite($vInfo & @CRLF)
    Sleep(100)
EndFunc
Edited by czardas
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...