_SleepEx und _MS (Konvertierung von ms)

  • * _SleepEx: eine "handlichere" Version von Sleep inklusiv einem Zeitbereich von Micro-Sekunden bis zu mehreren Tagen
    + verwendet die Funktion _HighPrecisionSleep(): ist wesentlich genauer als Sleep
    * _MS: Wandelt einfache Angaben in ms um (inklusiv Laufzeitkoorektur und direkter Verwendung mit Sleep bzw. _SleepEx)
    * _2MS: Direkte Rückgabe des Millisekunden Wertes

    !!! Angabe von Microsekunden (was zwar wenig Sinn macht ...) nur über _SleepEx("0:0:0:0.n") möglich.

    Beispiele und Funktionen:

    Spoiler anzeigen
    [autoit]

    Global $_SLEEPEX_CORR

    [/autoit] [autoit][/autoit] [autoit]

    Main()

    [/autoit] [autoit][/autoit] [autoit]

    Func Main()
    ; Laufzeitkorrektur fuer _SleepEx()
    ; - stimmt nicht ganz, macht aber dennoch das Ergebnis etwas genauer
    _SleepEx_Corr()
    ConsoleWrite($_SLEEPEX_CORR & @CRLF)

    [/autoit] [autoit][/autoit] [autoit]

    MsgBox(0,"2 Minuten, 15 Sekunden und 4 ms:", _2MS("0:2:15:4"))

    [/autoit] [autoit][/autoit] [autoit]

    Local $t = TimerInit()
    _SleepEx("00:00:02:0100") ; 2 sec, 100 ms
    ConsoleWrite(TimerDiff($t) & @CRLF)

    [/autoit] [autoit][/autoit] [autoit]

    Local $t = TimerInit()
    _SleepEx("0:0:0:4") ; 4 ms !!!
    ConsoleWrite(TimerDiff($t) & @CRLF)

    [/autoit] [autoit][/autoit] [autoit]

    Local $t = TimerInit()
    Sleep(_MS("0:0:1:20")) ; 1 sec 20 ms
    ConsoleWrite(TimerDiff($t) & @CRLF)

    [/autoit] [autoit][/autoit] [autoit]

    $t = TimerInit()
    _SleepEx(2) ; 2 sec
    ConsoleWrite(TimerDiff($t) & @CRLF)

    [/autoit] [autoit][/autoit] [autoit]

    $t = TimerInit()
    _SleepEx(1, "m") ; 1 min
    ConsoleWrite(TimerDiff($t) & @CRLF)

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    EndFunc ;==>Main

    [/autoit] [autoit][/autoit] [autoit]

    ; #FUNCTION# ===================================================================
    ; Name ..........: _SleepEx_Corr
    ; Description ...: Correction time for _SleepEx
    ; AutoIt Version : V3.3.0.0
    ; Syntax ........: _SleepEx_Corr()
    ; Parameter(s): .: $iMax - Optional: (Default = 10) : max correction time
    ; Return Value ..: Success - Global var $_SLEEPEX_CORR
    ; Failure -
    ; Author(s) .....: Thorsten Willert
    ; Date ..........: Sat Feb 06 14:10:40 CET 2010
    ; ==============================================================================
    Func _SleepEx_Corr($iMax = 10)
    Local $Time = 0, $t
    If Not IsDeclared("_SLEEPEX_CORR") Then Assign("_SLEEPEX_CORR", 0, 2)
    For $i = 0 To 4
    $t = TimerInit()
    _SleepEx("00:00:00:200")
    $Time += TimerDiff($t) - 200
    Next
    $_SLEEPEX_CORR = $Time / 5
    If $_SLEEPEX_CORR > $iMax Then $_SLEEPEX_CORR = $iMax
    EndFunc ;==>_SleepEx_Corr

    [/autoit] [autoit][/autoit] [autoit]

    ; #FUNCTION# ===================================================================
    ; Name ..........: _SleepEx
    ; Description ...: Extended sleep
    ; AutoIt Version : V3.3.0.0
    ; Requirement(s).: _MS(), _HighPrecisionSleep()
    ; Syntax ........: _SleepEx($vTime[, $sBase = "s"])
    ; Parameter(s): .: $vTime - in ms
    ; $sBase - Optional: (Default = "s") :
    ; | d = day
    ; | h = hour
    ; | m = minute
    ; | s = second
    ; | ms = millisecond
    ; Return Value ..: Success - 1
    ; Failure - 0
    ; Author(s) .....: Thorsten Willert
    ; Date ..........: Sat Feb 06 15:15:31 CET 2010
    ; Example .......: Yes
    ; _SleepEx("0:0:2:100") ; 2 sec, 100 ms
    ; ==============================================================================
    Func _SleepEx($vTime, $sBase = "s")
    If Not IsString($vTime) And $vTime < 1 Then Return 0
    $vTime = _MS($vTime, $sBase, True, False)
    Local $iaMS[1]

    [/autoit] [autoit][/autoit] [autoit]

    If $vTime < 2147483647 Then
    If IsDeclared("_SLEEPEX_CORR") And $vTime >= 500 Then $vTime -= $_SLEEPEX_CORR
    _HighPrecisionSleep($vTime * 1000)
    Return SetError(@error, 0, Not @error)
    Else
    Local $iTMP = $vTime
    Local $t = TimerInit()
    While $iTMP > 2147483647
    $iTMP -= 2147483647
    If IsDeclared("_SLEEPEX_CORR") Then $iTMP -= $_SLEEPEX_CORR
    $iaMS[UBound($iaMS) - 1] = $iTMP * 1000
    ReDim $iaMS[UBound($iaMS) + 1]
    WEnd
    $iaMS[0] -= TimerDiff($t) * 1000

    [/autoit] [autoit][/autoit] [autoit]

    For $i = 0 To UBound($iaMS) - 2
    _HighPrecisionSleep($iaMS[$i])
    If @error Then Return SetError(@error, 0, 0)
    Next
    Return SetError(0, 0, 1)
    EndIf
    EndFunc ;==>_SleepEx

    [/autoit] [autoit][/autoit] [autoit]

    ; #FUNCTION# ===================================================================
    ; Name ..........: _MS
    ; Description ...: Converts to ms
    ; AutoIt Version : V3.3.0.0
    ; Syntax ........: _MS($vTime[, $sBase = "s"[, $bCorr = True[, $bSleep = True]]])
    ; Parameter(s): .: $vTime - int + $sBase
    ; | "0:0:0:0" = hour:minute:second:millisecond
    ; $sBase - Optional: (Default = "s") :
    ; | d = day
    ; | h = hour
    ; | m = minute
    ; | s = second
    ; | ms = millisecond
    ; $bCorr - Optional: (Default = True) : subtracts the functions runtime from the return value
    ; $bSleep - Optional: (Default = True) : limits the return value for sleep to 2147483647 and sets @error to 3
    ; Return Value ..: Success - ms
    ; Failure - 0 / @error = 3, 2147483647
    ; @ERROR - 1 = incorrect format for "0:0:0:0"
    ; | 2 = incorrect $sBase parameter
    ; | 3 = $vTime > 2147483647 if $bSleep = True
    ; Author(s) .....: Thorsten Willert
    ; Date ..........: Sat Feb 06 15:25:11 CET 2010
    ; Example .......: Yes
    ; $iMS = _MS(2) ; 2 sec
    ; $iMS = _MS(1, "m") ; 1 min
    ; ==============================================================================
    Func _MS($vTime, $sBase = "s", $bCorr = True, $bSleep = True)
    Local $t = TimerInit()
    Local $iRet = 0
    Local $aTMP
    Local $aBase[4] = ["h", "d", "s", "ms"]

    [/autoit] [autoit][/autoit] [autoit]

    While 1
    If StringInStr($vTime, ":") Then
    $aTMP = StringSplit($vTime, ":", 2)
    If @error Or UBound($aTMP) <> 4 Then Return SetError(1, 0, 0)
    For $i = 0 To 3
    If $aTMP[$i] Then $iRet += _MS(Int($aTMP[$i]), $aBase[$i], $bCorr)
    Next
    ExitLoop
    Else
    Switch $sBase
    Case "ms"
    $iRet = $vTime
    ExitLoop
    Case "s"
    $iRet = $vTime * 1000
    ExitLoop
    Case "m"
    $iRet = $vTime * 60000
    ExitLoop
    Case "h"
    $iRet = $vTime * 360000
    ExitLoop
    Case "d"
    $iRet = $vTime * 86400000
    ExitLoop
    Case Else
    Return SetError(2, 0, 0)
    EndSwitch
    EndIf
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    ; maximum sleep time (24h)
    If $bSleep And $iRet > 2147483647 Then Return SetError(3, 0, 2147483647)

    [/autoit] [autoit][/autoit] [autoit]

    If $bCorr = True Then Return $iRet - TimerDiff($t)

    [/autoit] [autoit][/autoit] [autoit]

    Return $iRet
    EndFunc ;==>_MS

    [/autoit] [autoit][/autoit] [autoit]

    Func _2MS($vTime)
    Return _MS($vTime, "", False, False)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ; #FUNCTION#;===============================================================================
    ;
    ; Name...........: _HighPrecisionSleep()
    ; Description ...: Sleeps down to 0.1 microseconds
    ; Syntax.........: _HighPrecisionSleep( $iMicroSeconds, $hDll=False)
    ; Parameters ....: $iMicroSeconds - Amount of microseconds to sleep
    ; $hDll - Can be supplied so the UDF doesn't have to re-open the dll all the time.
    ; Return values .: None
    ; Author ........: Andreas Karlsson (monoceres)
    ; Modified.......:
    ; Remarks .......: Even though this has high precision you need to take into consideration that it will take some time for autoit to call the function.
    ; Related .......:
    ; Link ..........;
    ; Example .......; No
    ;
    ;;==========================================================================================
    Func _HighPrecisionSleep($iMicroSeconds, $hDll = False)
    Local $hStruct, $bLoaded
    If Not $hDll Then
    $hDll = DllOpen("ntdll.dll")
    If $hDLL = -1 Then Return SetError(1)
    $bLoaded = True
    EndIf
    $hStruct = DllStructCreate("int64 time;")
    DllStructSetData($hStruct, "time", -1 * ($iMicroSeconds * 10))
    DllCall($hDll, "dword", "ZwDelayExecution", "int", 0, "ptr", DllStructGetPtr($hStruct))
    If $bLoaded Then DllClose($hDll)
    EndFunc ;==>_HighPrecisionSleep

    [/autoit]

    2 Mal editiert, zuletzt von Stilgar (6. Februar 2010 um 18:51)

  • Schöne Sleep funktionen.
    Du könntest auch folgende noch einfügen:
    1 Nanosekunde = 10^-9 Sekunden
    1 Pikosekunde = 10^-12 Sekunden
    Dann merkt niemand mehr die Sleeps ;) (aber bitte nicht böse nehmen :D )
    Ich finde, es ist einfach alles richtig so, von der Schreibweise.
    Besser ein präzises Sleep mit viel Code als ein unpräzises Sleep mit wenig Code.
    Z.B.: Finde ich

    [autoit]

    _SleepEx("0:2:15:4")

    [/autoit]


    Viel einfacher als

    [autoit]

    Sleep(135004)

    [/autoit]

    Also Super UDF, weiter so! :thumbup: :thumbup:

    Meine Projekte:
    ClipBoard Manager (beendet)
    Gutes ClipBoard Verwaltungs Programm mit nützlichen Funktionen.

    HTML Creator (beendet)
    Nützliches Tool um schnell ein eigenes HTML Dokument zu erstellen.


  • Besser ein präzises Sleep mit viel Code als ein unpräzises Sleep mit wenig Code.


    Nur, dass das das präzise Sleep nmicht die COU-Last reduziert, da andauernd geprüft wird, wie viel Zeit schon vergangen ist ;)
    Edit: funktioniert ja doch. Da hab ich das irgendwo falsch gelesen ...
    Die Funktion kann man noch kürzen und beschleinigen ;) (1mal starten um die DLL zu laden mit z.B. _HighPrecisionSleep(0.1), danach muss das nicht mehr getan werden. )

    [autoit]

    ; #FUNCTION#;===============================================================================
    ;
    ; Name...........: _HighPrecisionSleep()
    ; Description ...: Sleeps down to 0.1 microseconds
    ; Syntax.........: _HighPrecisionSleep( $iMicroSeconds, $hDll=False)
    ; Parameters ....: $iMicroSeconds - Amount of microseconds to sleep
    ; Return values .: None
    ; Author ........: Andreas Karlsson (monoceres)
    ; Modified.......: Prog@ndy
    ; Remarks .......: Even though this has high precision you need to take into consideration that it will take some time for autoit to call the function.
    ; Related .......:
    ; Link ..........;
    ; Example .......; No
    ;
    ;;==========================================================================================
    Func _HighPrecisionSleep($iMicroSeconds)
    Local Static $hDLL = DllOpen("ntdll.dll")
    DllCall($hDll, "dword", "ZwDelayExecution", "int", 0, "int64*", -1 * ($iMicroSeconds * 10))
    If @error Then Return SetError(@error,0,0)
    Return 1
    EndFunc ;==>_HighPrecisionSleep

    [/autoit]

    Einmal editiert, zuletzt von progandy (7. Februar 2010 um 12:48)

  • Micro und Nanosekunden wären wohl etwas übetrieben :D

    @progandy:
    Danke für den Hinweis, wollte nur die Original Funktion nicht "umbauen".
    Was für eine CPU-Last? Die liegt hier während des "Sleeps" bei ziemlich genau 0%.


  • Was für eine CPU-Last? Die liegt hier während des "Sleeps" bei ziemlich genau 0%.


    Ja, hab ich auch bemerkt und auch schon dazueditiert. Da hab ich irgendwo ne falsche Info gelesen ^^
    PS: Der Aufruf von der modifizierten _HighPrecisionSleep-Funktion allein benötigt bei mir schon 15ms (bei 0.1 microsekunden) Kürzer geht es einfach nicht ^^ Bei 1Sekunde stimmt der Wet aber schon erstaunlich genau (+/- 2ms)