Jump to content
mistersquirrle

Avoid sleep in TrayGetMsg and GUIGetMsg

Recommended Posts

TL;DR: Anyway to bypass built in sleep on TrayGetMsg() and GUIGetMsg() ?

 

I'm currently working on a project that does some heavy array/ GDI+ processing, which depending what I have it do can take between 4s - 1min. During this time, I'd like to have the Tray icon (mainly, possibly also the GUI) for the program be responsive, so that if someone wanted to change actions or exit the script during this, they can without closing the process.

 

Currently I have my TrayGetMsg and GUIGetMsg captures in my main program loop, working great, and once I go into the array/ GDI+ functions I tried switching it to an AdlibRegister call, unregistering it once completed. The problem with this is that it's adding ~10-20% more time into those functions, which I'd like to avoid. As I understand it, and from the helpfile: "This function automatically idles the CPU when required so that it can be safely used in tight loops without hogging all the CPU." From what I've read/ seen/ tested, this adds a 10ms sleep into the calls. I would rather avoid that sleep all together.

 

The array/ GDI+ function that I'm doing peg the CPU at 100% (for its core) anyways, so that's not a concern of mine. My only concern for this is speed (and having things be responsive to other actions).

 

Here's an example:

Local $iBlockSize = 20, $iWidth = 1920, $iHeight = 1080, $aBigArray[$iWidth * $iHeight], $iPercentDone, $sLastMsg
Local $aSmallerArray[Int(Ceiling($iWidth / $iBlockSize)) * Int(Ceiling($iHeight / $iBlockSize))]
Local $sAdlib[] = ["Registered: ", "UnRegistered: ", "Registered to _FakeTray: "], $timer, $iIndexLength = UBound($aBigArray)
Local $ixBlocks = Int(Ceiling($iWidth / $iBlockSize)), $iBlockIndex, $iBlockX, $iBlockY

For $j = 0 To 2
    If $j = 0 Then
        AdlibRegister("_CheckTray", 100)
    ElseIf $j = 1 Then
        AdlibUnRegister("_CheckTray")
    ElseIf $j = 2 Then
        AdlibRegister("_FakeTray", 100)
    EndIf

    $timer = TimerInit()

    For $i = 0 To $iIndexLength - 1 ; Loop through $aBigArray

        $aBigArray[$i] = Random(1, 10, 1)

        $iPercentDone = Floor(($i / $iIndexLength * 100)) ; Hopefully quick maths to get progress
        If $sLastMsg <> "We are " & $iPercentDone & "% done" Then ; Check if we're on a new percent
            $sLastMsg = "We are " & $iPercentDone & "% done" ; If so, update the msg
            ToolTip($sLastMsg, 0, 0) ; And display the current progress
        EndIf

        $y = Floor($i / $iWidth) ; Convert index to Y coordinate
        $x = Floor($i - ($y * $iWidth)) ; Convert index to X coordinate

        $iBlockX = Floor($x / $iBlockSize) ; Convert X coord to xBlock coord
        $iBlockY = Floor($y / $iBlockSize) ; Convert Y coord to yBlock coord

        $iBlockIndex = Int($iBlockX + ($iBlockY * $ixBlocks)) ; Convert into a blockIndex
;~      If Mod($i, 10000) = 0 Then
;~          ConsoleWrite($iBlockIndex & " - " & $i & @CRLF)
;~      EndIf

        $aSmallerArray[$iBlockIndex] += Int($aBigArray[$i]) ; Add into $aSmallerArray
    Next
    ConsoleWrite("Time to run with Adlib" & $sAdlib[$j] & TimerDiff($timer) & @CRLF)
Next

Func _CheckTray()
    Switch TrayGetMsg()
        Case "Meow"
            Return

        Case "Woof"
            Return

    EndSwitch
EndFunc   ;==>_CheckTray

Func _FakeTray()
    Local $sMeow = "Oink"
    Switch $sMeow
        Case "Meow"
            Return

        Case "Woof"
            Return

    EndSwitch
EndFunc   ;==>_FakeTray

Exit

On my system, this takes ~1 minute to run, output:
 

Time to run with AdlibRegistered: 19649.335
Time to run with AdlibUnRegistered: 16264.4124
Time to run with AdlibRegistered to _FakeTray: 16860.1283

>Exit code: 0    Time: 53.92

As you can see, it's ~20.8% faster without the Adlib check, and ~16.5% faster using a (hopefully) reproduction of TrayGetMsg() without the built in sleep. These timings vary, but it's consistently much faster without the TrayGetMsg() sleep (unless it's just that slow). I've used the OnEventModes, and those also slow down performance, more so than just using the GetMsgs, so those are out (but effective, and pretty easy to use).

Edited by mistersquirrle

RAWR! I'm hungry :( Feed the panda squirrle

Share this post


Link to post
Share on other sites

I'd be OK with a 'No', I just want to know :lol:

 

Currently I'm using the Tray/GUIGetMsg in my program, which works fine, and I've tried the OnEvent's as well, so it'll come down to which has a smaller impact on performance. I've been doing a lot of performance testing of different things, and having the OnEvent modes on really slows things down. I'm thinking at the moment though that it may be best for performance to run the OnEventModes while in my main loop, and switch to the GetMsg's / adlib (at a higher interval) for my array/GDI functions, but I'm not sure if switching between those modes often would have any ill effect.

 

Again, if there's a way to bypass the sleep built into the *GetMsgs that would easily solve these problems, and CPU hogging isn't an issue for this/me.

 

Or -- if there's a different way that I get receive the GUI/ Tray msgs, such as with some other Windows functions/ DLLs, I just don't know enough in that area to figure out what I would need to look at. For GUIGetMsg, I was looking at GUIRegisterMsg(), but the main issue right now is the TrayGetMsg as that's always in the main loop, the GUI isn't always around.


RAWR! I'm hungry :( Feed the panda squirrle

Share this post


Link to post
Share on other sites
On 8/21/2018 at 5:45 AM, mistersquirrle said:

TL;DR: Anyway to bypass built in sleep on TrayGetMsg() and GUIGetMsg() ?

Use Event mode for both.

Jos

Share this post


Link to post
Share on other sites

Thanks for the reply Jos, but the OnEvent mode also has performance issues. Using that same test, but with the OnEvent modes on (all times in ms):

Time to run with Tray off, GUI off: 18216.3572
Time to run with Tray On, GUI off:  19452.3151
Time to run with Tray off, GUI On:  19975.8837
Time to run with Tray On, GUI On:   22121.3507

So running with both on in that test is slower, unfortunately. I was originally using the OnEvent modes until I discovered that they slowed everything down. I had done some other speed tests on Select vs Switch vs Ifs as well, and you can see it a lot there:

Tray and GUI OnEventMode OFF                |                       |   Tray and GUI OnEventMode ON     
------------------------------------------------------------------------------------------------------------------
Select      |   Switch      |   Ifs                                 |   Select      |   Switch      |   Ifs
28940.94468 |   19846.75708 |   34120.26846 |   10,000,000 times    |   39401.7251  |   29542.56247 |   62362.88815
-------------------------------------------------------------------------------------------------------------------
3140.979716 |   1956.855577 |   3363.471969 |   Time for 1mil       |   4024.597562 |   2930.187909 |   6344.789068

The above averages were over 6 runs of 1,000,000 times for each. This was a simple statement seeing if a variable = 1. I did a second run with checking against an array with two indexes values (ie. If $aTmp[0] = 1 And $aTmp[1] = 1 Then):

Tray and GUI OnEventMode OFF                |                       |   Tray and GUI OnEventMode ON
-------------------------------------------------------------------------------------------------------------------
Select      |   Switch      |   Ifs         |                       |   Select      |   Switch      |   Ifs
2983.793303 |   1481.685642 |   3709.658693 |   Time for 1mil       |   3703.603641 |   2753.622659 |   7324.438944

This again is the time to run each statement 1 million times, averaged over 6 runs. 

Edited by mistersquirrle

RAWR! I'm hungry :( Feed the panda squirrle

Share this post


Link to post
Share on other sites

I have run the code in the first post with these results:

Time to run with AdlibRegistered: 14571.9029530593
Time to run with AdlibUnRegistered: 13025.2308415184
Time to run with AdlibRegistered to _FakeTray: 13365.1403195613

 

A few comments:

  • A large number of loops are much faster in 64 bit code.
  • The outer loop (j-loop) is always faster in second and third passes. In this code about 1 second faster. This gives incorrect results. It should be taken into account by introducing an initial first run.
  • $aSmallerArray is not be reset between each pass.
  • Tooltip: If Not Mod( $i, 20736 ) Then ToolTip("We are " & $i/20736 & "% done", 0, 0)
  • Added _ArrayDisplayEx that can display large arrays

New code:

#AutoIt3Wrapper_UseX64=y

#AutoIt3Wrapper_Au3Check_Parameters=-d -w- 1 -w 2 -w 3 -w 4 -w 5 -w 6

#include "Display\Functions\ArrayDisplayEx\ArrayDisplayEx.au3"

Global $iBlockSize = 20, $iWidth = 1920, $iHeight = 1080, $iIndexLength = $iWidth * $iHeight, $iPercentDone, $sLastMsg
Global $aBigArray[$iIndexLength],  $aSmallerArray[$iWidth / $iBlockSize * $iHeight / $iBlockSize]
Global $sAdlib = [" First run: ", "Registered: ", "UnRegistered: ", "Registered to _FakeTray: "]
Global $ixBlocks = $iWidth / $iBlockSize, $iBlockIndex, $iBlockX, $iBlockY, $timer, $x, $y

For $j = 0 To 3
    If $j = 1 Then
        AdlibRegister("_CheckTray", 100)
    ElseIf $j = 2 Then
        AdlibUnRegister("_CheckTray")
    ElseIf $j = 3 Then
        AdlibRegister("_FakeTray", 100)
    EndIf

    $aSmallerArray = 0
    Dim $aSmallerArray[$iWidth / $iBlockSize * $iHeight / $iBlockSize]

    $timer = TimerInit()

    For $i = 0 To $iIndexLength - 1 ; Loop through $aBigArray

        $aBigArray[$i] = Random(1, 10, 1)

        If Not Mod( $i, 20736 ) Then ToolTip("We are " & $i/20736 & "% done", 0, 0)

        $y = Floor($i / $iWidth) ; Convert index to Y coordinate
        $x = Floor($i - ($y * $iWidth)) ; Convert index to X coordinate

        $iBlockX = Floor($x / $iBlockSize) ; Convert X coord to xBlock coord
        $iBlockY = Floor($y / $iBlockSize) ; Convert Y coord to yBlock coord

        $iBlockIndex = Int($iBlockX + ($iBlockY * $ixBlocks)) ; Convert into a blockIndex

        $aSmallerArray[$iBlockIndex] += Int($aBigArray[$i]) ; Add into $aSmallerArray
    Next
    ConsoleWrite("Time to run with Adlib" & $sAdlib[$j] & TimerDiff($timer) & @CRLF)
Next

Global $aWidth = [ 0, 65 ]
Global $aAlign = [ [ 0, "l" ], [ 1, "r" ] ]
Global $aFeatures = [ [ "ColWidthMin", $aWidth ], _
                     [ "ColAlign",    $aAlign ] ]
_ArrayDisplayEx( $aBigArray, "$aBigArray", "", 0, $aFeatures )
_ArrayDisplayEx( $aSmallerArray, "$aSmallerArray", "", 0, $aFeatures )

Func _CheckTray()
    Switch TrayGetMsg()
        Case "Meow"
            Return

        Case "Woof"
            Return

    EndSwitch
EndFunc   ;==>_CheckTray

Func _FakeTray()
    Local $sMeow = "Oink"
    Switch $sMeow
        Case "Meow"
            Return

        Case "Woof"
            Return

    EndSwitch
EndFunc   ;==>_FakeTray

Exit

#cs
Time to run with Adlib First run: 9354.58487313101
Time to run with AdlibRegistered: 8572.65596364715
Time to run with AdlibUnRegistered: 8436.5804675481
Time to run with AdlibRegistered to _FakeTray: 8573.66191708517
#ce

And results:

Time to run with Adlib First run: 9354.58487313101
Time to run with AdlibRegistered: 8572.65596364715
Time to run with AdlibUnRegistered: 8436.5804675481
Time to run with AdlibRegistered to _FakeTray: 8573.66191708517

Now there is not much difference between the last 3 results.

 

For arrays with 2 million elements, it's a great advantage to use compiled code. Since UDFs already exist to execute VB code (and C# code) in an AutoIt script through the .NET Framework, it's not difficult.

c.vb:

Imports System
Class Au3Class
  Dim aSmallerArray As Integer()

  Public Function MyMethod1( iBlockSize As Integer, iWidth As Integer, iHeight As Integer ) As Integer()
    Dim ixBlocks As Integer = iWidth / iBlockSize
    ReDim aSmallerArray(ixBlocks * iHeight/iBlockSize - 1)
    Dim iIndexLength As Integer = iWidth * iHeight
    Dim aBigArray(iIndexLength-1) As Integer
    Dim oRnd As New Random()

    Dim x, y, iBlockX, iBlockY, iBlockIndex As Integer
    For i As Integer = 0 To iIndexLength - 1
      aBigArray(i) = oRnd.Next( 1, 10+1 )
      y = Math.Floor( i / iWidth ) : x = Math.Floor( i - y * iWidth )
      iBlockX = Math.Floor( x / iBlockSize ) : iBlockY = Math.Floor( y / iBlockSize )
      iBlockIndex = iBlockX + iBlockY * ixBlocks
      aSmallerArray(iBlockIndex) += aBigArray(i)
    Next

    Return aBigArray
  End Function

  Public Function MyMethod2() As Integer()
    Return aSmallerArray
  End Function
End Class

c.au3:

#AutoIt3Wrapper_UseX64=y

#AutoIt3Wrapper_Au3Check_Parameters=-d -w- 1 -w 2 -w 3 -w 4 -w 5 -w 6

#include "DotNet\DotNetAll.au3"
#include "Display\Functions\ArrayDisplayEx\ArrayDisplayEx.au3"

Opt( "MustDeclareVars", 1 )

Example()

Func Example()
  Local $oNetCode = DotNet_LoadVBcode( FileRead( "c.vb" ), "System.dll" )
  Local $oAu3Class = DotNet_CreateObject( $oNetCode, "Au3Class" )
  Local $timer = TimerInit()
  Local $aBigArray = $oAu3Class.MyMethod1( 20, 1920, 1080 )
  Local $aSmallerArray = $oAu3Class.MyMethod2()
  ConsoleWrite( TimerDiff( $timer ) & @CRLF ) ; 221.589018567889

  Local $aWidth = [ 0, 65 ]
  Local $aAlign = [ [ 0, "l" ], [ 1, "r" ] ]
  Local $aFeatures = [ [ "ColWidthMin", $aWidth ], _
                       [ "ColAlign",    $aAlign ] ]
  _ArrayDisplayEx( $aBigArray, "$aBigArray", "", 0, $aFeatures )
  _ArrayDisplayEx( $aSmallerArray, "$aSmallerArray", "", 0, $aFeatures )
EndFunc

Note the time: 221 milliseconds.

 

You cannot do anything about the Sleep function in TrayGetMsg() and GUIGetMsg(), but you can completely avoid the functions by using Windows messages directly through GUIRegisterMsg() (still in MessageLoop mode).

 

Tests.7z

Edited by LarsJ

Share this post


Link to post
Share on other sites

@Jos I don't have the same code, but it was something like this (basic, and also taking a note from LarsJ about a first run):

;~ #AutoIt3Wrapper_UseX64=Y
Local $timer
Local $iMeow = 1

For $j = 2 To 0 Step -1

    If $j < 2 Then AutoItSetOption("TrayOnEventMode", $j)
    If $j < 2 Then AutoItSetOption("GUIOnEventMode", $j)

    ConsoleWrite("Tray/GUI OnEventMode: " & $j & @CRLF)

    $timer = TimerInit()
    For $i = 0 To 999999
        Select
            Case $iMeow = 0
            Case $iMeow = 2
            Case $iMeow = 1
        EndSelect
    Next
    ConsoleWrite("Select time:  " & TimerDiff($timer) & @CRLF)

    $timer = TimerInit()
    For $i = 0 To 999999
        Switch $iMeow
            Case 0
            Case 2
            Case 1
        EndSwitch
    Next
    ConsoleWrite("Switch time:  " & TimerDiff($timer) & @CRLF)

    $timer = TimerInit()
    For $i = 0 To 999999
        If $iMeow = 0 Then
        EndIf
        If $iMeow = 2 Then
        EndIf
        If $iMeow = 1 Then
        EndIf
    Next
    ConsoleWrite("Ifs time: " & TimerDiff($timer) & @CRLF)
Next


#cs
First run (Tray/GUI OnEvent not set/ changed [default])
  Select time:  966.3338
  Switch time:  898.1769
  Ifs time:     1543.816
Tray/GUI OnEventMode: 1
  Select time:  1642.5594
  Switch time:  1486.2358
  Ifs time:     3028.6555
Tray/GUI OnEventMode: 0
  Select time:  908.7544
  Switch time:  523.0475
  Ifs time:     1135.5656
#ce

----------

@LarsJ Thanks for the tips, trying your code, here's my results (note that I had to disable your included file/ functions, as even when I downloaded it and put a direct path to it, it said that it wouldn't include it and gave a lot of warnings/ error/ undefineds):

Time to run with Adlib First run: 12885.4199
Time to run with AdlibRegistered: 11540.2438
Time to run with AdlibUnRegistered: 11087.015
Time to run with AdlibRegistered to _FakeTray: 11600.5445

That does provide interesting results as the AdlibRegistered run with TrayGetMsg is slightly faster than without TrayGetMsg for both of us. I had also looked at your topic a bit before, and it's a bit much for me to get my head around, but I was going to look into that some more to speed up some data processing parts of my program like this, so I appreciate this example.

 

As for the GUIRegisterMsg, I know how to use it for an actual GUI, but I'm not sure how to use it for the Tray icon?


RAWR! I'm hungry :( Feed the panda squirrle

Share this post


Link to post
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

  • Similar Content

    • By simonc8
      I have a script which executes sleep for a couple of hours then carries out instructions. Does the running AutoIt script prevent the computer from entering sleep mode during this time? If not, is there something I can add to the AutoIt script to keep the computer awake?
      Grateful for advice.
    • By naru
      I have script Like This :
      Opt("TrayAutoPause",0)
      $var = Ping("www.google.com")
      If not @error Then
      WinActivate ( "testapp")
      ControlClick ( "testapp", "", "[Savetest]")
      ControlSend ( " :: Gujarat TPDS  - eFPS :: Version - 2.2.0.0  - [eFPS Bill]", "", "[NAME:btnSavebyFP]", "{enter}")
      WinWait(":: Aadhar/EID/Verification Number Entry ::")
      ControlClick(":: Aadhar/EID/Verification Number Entry ::", "", "[NAME:btnNext]")
      If WinExists ("Aadhar : Length Check") Then
         ControlClick("Aadhar : Length Check", "", "[CLASS:Button; INSTANCE:1]")
         ControlSend(":: Aadhar/EID/Verification Number Entry ::", "", "[NAME:txtAadharNumber]", "{backspace}")
         ControlSend(":: Aadhar/EID/Verification Number Entry ::", "", "[NAME:txtAadharNumber]", "^v")
         ControlClick(":: Aadhar/EID/Verification Number Entry ::", "", "[NAME:btnNext]")
         WinWait(" :: Barcoded Ration Card Members - Biometric Verification/Check Utility ::")
         ControlSend("[Class:WindowsForms10.Window.8.app.0.378734a]", "", "[NAME:PictureBox2]", "{tab} {enter}")
         Sleep(5600)
         RunWait("rasdial /disconnect", "", @SW_HIDE) ; Stop connect from start
         RunWait("rasdial Internet", "", @SW_HIDE) ; Connect again
         Exit
      EndIf
      WinWait(" :: Barcoded Ration Card Members - Biometric Verification/Check Utility ::", "", 1)
      ControlSend("[Class:WindowsForms10.Window.8.app.0.378734a]", "", "[NAME:PictureBox2]", "{tab} {enter}")
      Sleep(5600)
      RunWait("rasdial /disconnect", "", @SW_HIDE) ; Stop connect from start
      RunWait("rasdial Internet", "", @SW_HIDE) ; Connect again
      Exit
      Else
         #include <MsgBoxConstants.au3>
         MsgBox($MB_TOPMOST, "Connection Status", "Internet is not Connected")
      Exit
      Endif
    • By naru
      How can i add sleep command using internet speed.
      If my internet speed is 40-50Kbps then sleep for 5 seconds,
      If my internet speed is 30-40Kbps then sleep for 4 seconds,
      If my internet speed is 20-30Kbps then sleep for 3 seconds.

      *Sleep command used bitween my costom script, Example,
      RunWait("rasdial /disconnect", "", @SW_HIDE) ; Stop connect from start
      Sleep(5000)
      RunWait("rasdial Internet", "", @SW_HIDE) ; Connect again
       
    • By lacamel
      Hi there,
      I did a short script to simulate mouse click when pixel change is detected on a small section of the screen. I recorded the screen many times to see the accuracy of the script and it seems though response time varies widely.
      Here's the script 
      $checksum = pixelchecksum (400,250, 402,252)
      While $checksum = pixelchecksum (400,250, 402,252)
      Sleep (50)
      Wend
      Sleep (300)
      Mouseclick("left", 450,300, 1, 0)
      Counting from the pixel change to the mouse click, i get response times anywhere between 370ms and 550ms. I've tried running au3 and exe, changed sleep times but never gotten an accurate response time based on the script. Any ideas why?
    • By InunoTaishou
      Update 2017-04-21:
      Added a timeout My previous attempt of checking that the function is valid was not working. Added a 1 time function call before entering the While loop to test the function. Now sets error to $SLEEP_UNTIL_INVALID_CALL if the function supplied is does not exist or invalid arguments supplied Added an @Error value $SLEEP_UNTIL_TIMEOUT_REACHED, set when the condition was not met but timeout reached Update 2017-04-25:
      Thanks to @jguinchfor letting me know about Execute(). Greatly simplified the loop (didn't know that Execute would execute a function call statement)
      Any strings passed to the SleepUntil() function need to be enclosed in " or ' (I.e', SleepUntil("ConsoleWrite('This is a test' & @LF)")) Adjusted SleepUntil() to use the Execute() function instead Inspired by a very vague topic, and completely unnecessary, I had fun trying to making this up. A function that will sleep until the conditional statement, or function call statement, provided executes to the condition you want! I know, completely useless!!! It's pretty interesting actually. Instead of having to write multiple while loops per conditions, you just need to use SleepUntil and set your own condition.
      Basic syntax:
      SleepUntil("$iMyNumber = 100") Will sleep until the variable in your script $iMyNumber is 100. All conditional operators are supported (=, <>, >=, <=, >, and <). Currently does not support multiple conditions (i.e., $iMyNumber > 100 and $iMyNumber < 1000).
      More advanced syntax, using a value returned from a function call:
      SleepUntil("TimerDiff(" & TimerInit() & ") > 5000") Well check the value returned from TimerDiff using the value returned from TimerInit() and stop sleeping once it's > 5000 (5 seconds).
      Anyways, better to show through the example.
      Example.au3
      #include <String.au3> #include <Array.au3> #include <GUIConstants.au3> #include <GuiEdit.au3> #include "SleepUntil.au3" AutoItSetOption("GUICloseOnESC", 0) Global $sName = "Test" Global $bBool = True Global $iInt = -1 Global $dDouble = 0.0 Global $sMsg = "Welcome," & @CRLF & _ "The SleepUntil function can use a function to check against a condition or just a regular conditional statement. " & _ "I.e. $iValue = 300" & @CRLF & "A basic conditional example would be" & @CRLF & @TAB & _ "Global $bWaiting = True" & @CRLF & @TAB & _ 'SleepUntil("$bWaiting <> $bWaiting")' & @CRLF & _ "This is a good example of having some kind of global flag where you want to wait until the user triggers the flag to not be true" & @CRLF & @CRLF & _ "The first set of examples will use function calls to compare against the condition value." & @CRLF & _ "First example calls GUIGetMsg using the with no arguments and sleeps until the value returned is " & _ "$GUI_EVENT_CLOSE" & @CRLF & @CRLF & _ "Syntax for the function call for SleepUntil is like normal:" & @CRLF & _ 'SleepUntil("FunctionName(Argument1, Argument2, ArgumnetN) (Condition Operator) Value' & @CRLF & _ 'Example (Where function call has arguments)' & @CRLF & @TAB & _ 'Global $iTimer = TimerInit()' & @CRLF & @TAB & _ 'SleepUntil("TimerDiff(" & $iTimer & ") >= 5000")' & @CRLF & @CRLF & _ "Example (Where no arguments are needed for the function)" & @CRLF & @TAB & _ 'SleepUntil("GUIGetMsg() = $GUI_EVENT_CLOSE")' & @CRLF & @CRLF & _ "The first example will start once you close this window!" Global $hMain = GUICreate("Introduction", 800, 600, 0, 0, BitOR($WS_SIZEBOX, $WS_MAXIMIZEBOX, $WS_MINIMIZEBOX)) Global $edtEdit = GUICtrlCreateEdit($sMsg, 10, 10, 775, 555, $ES_MULTILINE) GUICtrlSetBkColor($edtEdit, 0x1F1F1F) GUICtrlSetColor($edtEdit, 0xF1F1F1) GUICtrlSetFont($edtEdit, 11, 400, "", "Consolas") GUICtrlSetResizing($edtEdit, $GUI_DOCKLEFT + $GUI_DOCKRIGHT + $GUI_DOCKTOP + $GUI_DOCKBOTTOM) GUISetState(@SW_SHOWMAXIMIZED) _GUICtrlEdit_SetSel(GUICtrlGetHandle($edtEdit), 0, 0) ; Slep until person running this example script closes the GUI or it reaches the 30 second timeout SleepUntil("GUIGetMsg() = $GUI_EVENT_CLOSE", 50, 30000) GUIDelete($hMain) MsgBox("", "Timer", "Starting the examples. The next sleep will last until 2 seconds have passed") ; Sleep until TimerDif(Timer Created) > 2000 ToolTip("Sleeping until 2 seconds has passed", 0, 0) SleepUntil("TimerDiff(" & TimerInit() & ") >= 2000") MsgBox("", "Timer", "2 Seconds has passed. Met condition and left sleep function") ; Sleep until the call to ConsoleWrite3Times is >= 3 ToolTip("Sleeping until the function ConsoleWrite3Times() as been called three times", 0, 0) SleepUntil("ConsoleWrite3Times('This is a test!') >= 3", 500) MsgBox("", "Print 3 Times", "Did ConsoleWrite 3 times. Met condition needed and left sleep function") MsgBox("", "Next", "Next SleepUntil examples can be met by pressing the {F1} Key to trigger the conditions" & @CRLF & _ "Next example will sleep until $sName = InunoTaishou") HotKeySet("{F1}", SetName) ; Sleep until user presses {F1} and changes $sName = InunoTaishou ToolTip("$sName = " & $sName, 0, 0) SleepUntil("$sName = 'InunoTaishou'", 100) MsgBox("", $sName, "Name has been updated to " & $sName & ". Met condition needed and left sleep function" & @CRLF & _ "Next example will sleep until $bBool <> True") ; Sleep until user preses {F1} and $bBool <> True ToolTip("$bBool = " & $bBool, 0, 0) SleepUntil("$bBool <> " & $bBool, 100) MsgBox("", $bBool, "Bool has been updated to " & $bBool & ". Met condition needed and left sleep function" & @CRLF & _ "Next example will sleep until $iInt > 0") ; Sleep until user presses {F1} and $iInt > 0 ToolTip("$iInt = " & $iInt, 0, 0) SleepUntil("$iInt > 0", 100) MsgBox("", $iInt, "Int has been updated to " & $iInt & ". Met condition needed and left sleep function" & @CRLF & _ "Next example will sleep until $dDouble = 99.99") ; Sleep until user presses {F1} and $dDouble = 99.99 ToolTip("$dDouble = " & $dDouble, 0, 0) SleepUntil("$dDouble = 99.99", 100) MsgBox("", $dDouble, "Double has been updated to " & $dDouble & ". Met condition needed and left sleep function" & @CRLF & _ "Next example will sleep until function Print is called with the msg provided") Local $sMsgToPrint = InputBox("Message", "What message should be used for ConsoleWrite?", "This is a the default msg!") SleepUntil("Print('" & $sMsgToPrint & "', " & InputBox("Times?", "How many times to print " & $sMsgToPrint & "?", 10) & ") = '" & $sMsgToPrint & "'") MsgBox("", "Print", "Congrats! That's all the examples I have") Func ConsoleWrite3Times($sMsg) Local Static $iPrint = 0 $iPrint += 1 ConsoleWrite("[" & $iPrint & "] " & $sMsg & @LF) Return $iPrint EndFunc Func Print($sMsg, $iTimes) If ($iTimes < 1) Then $iTimes = 1 For $i = 1 to $iTimes ConsoleWrite($sMsg & @LF) Next Return $sMsg EndFunc Func SetName() $sName = "InunoTaishou" HotKeySet("{F1}", SetBool) EndFunc ;==>SetName Func SetBool() $bBool = False HotKeySet("{F1}", SetInt) EndFunc ;==>SetBool Func SetInt() $iInt = 100 HotKeySet("{F1}", SetDouble) EndFunc ;==>SetInt Func SetDouble() $dDouble = 99.99 EndFunc ;==>SetDouble SleepUnti.au3
      #include-once #include <String.au3> Global Const $SLEEP_UNTIL_INVALID_EXECUTE = -100 Global Const $SLEEP_UNTIL_TIMEOUT_REACHED = -101 ; #AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w- 4 -w 5 -w 6 -w- 7 ; #CURRENT# ===================================================================================================================== ; SleepUntil: Sleeps until the condition statement supplied meets the requirements ; =============================================================================================================================== ; #FUNCTION# ==================================================================================================================== ; Name ..........: SleepUntil ; Description ...: Sleeps until the condition supplied is met. ; Syntax ........: SleepUntil($sConditionStatement[, $iTime = 100[, $iTimeout = Default]]) ; Parameters ....: $sConditionStatement - String formatted condition statement ; $iTime - (Optional) Time (In Milliseconds) to sleep between each check of the condition ; $iTimeout - (Optional) Timeout (In Milliseconds) to stop sleeping if condition not met ; Return values .: Success - Returns True when the condition is met ; Failure - Returns False and Sets the @Error flag ; -100 ($SLEEP_UNTIL_INVALID_EXECUTE): Function supplied does not exist or parameters supplied do not match ; the function called ; -101 ($SLEEP_UNTIL_TIMEOUT_REACHED): Timeout was reached but the condition was not met ; Author ........: InunoTaishou, jguinch for letting me know about Execute() ; Thanks jguinch! Greatly simplified the script ; Remarks .......: The $sConditionStatement parameter can be a simple $vVar = Value or can use the value returned from a function call ; to sleep. ; Proper syntax for a function call is a normal AutoIt function call: "MsgBox(0, 'Title', 'Message')" ; Example .......: Yes ; =============================================================================================================================== Func SleepUntil($sConditionStatement, $iTime = 100, $iTimeout = Default) Local $iTimer = ($iTimeout ? TimerInit() : Null) While (Not Execute($sConditionStatement)) If (@Error) Then Return SetError($SLEEP_UNTIL_INVALID_EXECUTE, 0, False) If ($iTimeout and TimerDiff($iTimer) >= $iTimeout) Then Return SetError($SLEEP_UNTIL_TIMEOUT_REACHED, 0, False) Sleep($iTime) WEnd Return True EndFunc ;==>SleepUntil Edit: Did a test call to the function to make sure it's valid. checking for the 0xDEAD and 0xBEEF errors inside the while loops wasn't working since the _EvalCondition was being called right after it.
      Edit: Forgot about the _ that can be used in function calls. Added the _ to the StringRegExp
×
×
  • Create New...