Search code examples
user-interfacesleepautoit

User interface becomes unresponsive when calling Sleep()


Sleep() is causing issues when pressing buttons.

I have an If loop with random delays (up to 10 seconds) between each mouse move/-click. However, when Sleep() is called the script stops responding to clicks on Close and Stop buttons of its user interface:

#cs ----------------------------------------------------------------------------
    Author: JesterRM
    Website: N/A
#ce ----------------------------------------------------------------------------

#include <GUIConstantsEx.au3>
#include <MsgBoxConstants.au3>
#include <IE.au3>

;Comments On Information
;Set Mouse Position - MouseMove ( x, y)
;Mouse Click At Current Position - MouseClick ("Button")
;Wait Between Each Click Local $hTimer = TimerInit()>insert Link Break< Sleep(TIME)
;Random Sleep Time Sleep(Random(1000, 10000, 1)) = Random Sleep between 1 and 10 seconds
Opt('MustDeclareVars', 1)
MainGUI()

Func MainGUI()
    Local $Button1, $Button2, $Button3, $msg, $count, $OBJECT, $OBJECT_CTRL, $hTimer
    Global $count, $OBJECT, $OBJECT_CTRL

    $count = 0
    GUICreate("FREE KaW Bot V0.01", 1000, 650)
    ; Button Position and Names
    Opt("GUICoordMode", 2)
    $Button1 = GUICtrlCreateButton("Start", 370, 30, 100)
    $Button2 = GUICtrlCreateButton("Stop", 10, -1, 100)
    $Button3 = GUICtrlCreateButton("Close", 10, -1, 100)
    ;Create Internet Explorer in Window
    $OBJECT = ObjCreate("Shell.Explorer.2")
    $OBJECT_CTRL = GUICtrlCreateObj($OBJECT, -650, 20, 900, 550)
    GUISetState()
    _IECreateEmbedded()
    _IENavigate($OBJECT, "http://www.kingdomsatwar.com/play/")
    GUISetState()

    ; Run the GUI until the window is closed
    While 1
        $msg = GUIGetMsg()
        Select
            Case $msg = $GUI_EVENT_CLOSE
                ExitLoop
            ; Button PopUp Messages

            ; Start The Bot
            Case $msg = $Button1
                MsgBox(0, 'Start', 'Starting Bot in 10 Seconds after PopUp Closes')
                Sleep(10000)
                $count = 1
                If $count = 1 Then
                    Do
                        MouseMove(800, 100)
                        ; Begin The Timer and Store The Handle in a Variable
                        Local $hTimer = TimerInit()
                        ; Sleep For 3 Seconds
                        Sleep(Random(1000, 7000, 1))
                        Local $fDiff = TimerDiff($hTimer) ; Find the difference in time from the previous call of TimerInit. The variable we stored the TimerInit handlem is passed as the "handle" to TimerDiff.
                        MsgBox($MB_SYSTEMMODAL, "Time Difference", $fDiff)
                        MouseMove(200, 453)
                        ; Begin The Timer and Store The Handle in a Variable
                        Local $hTimer = TimerInit()
                        ; Sleep For 3 Seconds
                        Sleep(Random(1000, 7000, 1))
                        Local $fDiff = TimerDiff($hTimer) ; Find the difference in time from the previous call of TimerInit. The variable we stored the TimerInit handlem is passed as the "handle" to TimerDiff.
                        MsgBox($MB_SYSTEMMODAL, "Time Difference", $fDiff)
                    Until $count = 0
                Else
                    MsgBox(0, 'Stop', 'Stopping Bot')
                EndIf

            ; Stop The Bot
            Case $msg = $Button2
                MsgBox(0, 'Stop', 'Stopping Bot')
                $count = 0

            ; Close The Bot
            Case $msg = $Button3
                MsgBox(0, 'Close', 'Closing Bot')
                Exit
        EndSelect
    WEnd
EndFunc

How could I fix this?


Solution

  • As per AutoIt Wiki - Interrupting a running function:

    AutoIt queues function calls in both OnEvent and MessageLoop modes. This means that it waits until a function is finished and the code is back in your idle While...WEnd loop before running the next.

    Thus Sleep() delays processing of GUI messages. A workaround would be to contain Sleep() within a function that can be interrupted. Example:

    Func _SleepInterrupted(ByRef $bStateInterrupt, Const $iTimeSleep, Const $iTimeInterrupt = 500)
        Local Const $iParts     = Ceiling($iTimeSleep / $iTimeInterrupt)
        Local Const $iRemainder = $iTimeSleep - ($iTimeInterrupt * Floor($iTimeSleep / $iTimeInterrupt))
        Local       $iCurrent   = $iTimeInterrupt
        Local       $iReturn    = 0
    
        For $i1 = 1 To $iParts
    
            If $bStateInterrupt Then
                $iReturn = 1
                ExitLoop 1
            EndIf
    
            If $i1 = $iParts And $iRemainder Then $iCurrent = $iRemainder
            Sleep($iCurrent)
    
        Next
    
        Return $iReturn
    EndFunc
    
    • If (anywhere in the process) $bStateInterrupt evaluates to True the function will return 1 immediately (disregarding time left). It returns 0 if uninterrupted.
    • $iTimeSleep defines total duration (in ms) for Sleep().
    • $iTimeInterrupt defines delay (in ms) between periodic checks.

    Breaking up total time enables OnEvent- and MessageLoop events to be processed after each segment (every 0.5 seconds if $iTimeInterrupt = 500). Visual (simplified) explanation:

    SleepInterrupted()