Jump to content

Schedule a function call after 3 minutes without pausing the script


ppat
 Share

Recommended Posts

Is this possible in AutoIt?

[do something]

[in 3 minutes, launch this procedure: do_stuff(12,32)]

[immediately continue to do something else without waiting for the 3 minutes]


          Func do_stuff($param1, $param2)

          EndFunc

I know how to launch a Func after a certain given amount of time, usign loops. Basically, loops pause the script until the time is reached. I want something different: I want to program the launch of a function (with parameters) after a given time, but in the meantime continue to execute the script.

Maybe AutoIt does not have this possibility to run "parallel threads". I recall using a programming language where this was possible, Javascript if I recall well.

I guess the closest keyword would be "timer" and I could find _Timer_SetTimer in Autoit Help file. But a handle must be passed (no handle in my case), and callback functions do not accept parameters, so this is not exactly what I am looking for. Any suggestion?

Link to comment
Share on other sites

This has been asked many times, maybe search first?

Multithreading is not a feature of AutoIt.

The handle can be 0 if I remember rightly.

Post your full code :)

Cheers,

Brett

Link to comment
Share on other sites

My code is:

MsgBox(0, "Start", "Program start")

; I would like here and instruction: "Launch display_message("Hello", "Late execution") in 3 minutes from now

MsgBox(0, "Last", "Last instruction in script")


Func display_message($title, $message)

    MsgBox(0, $title, $message)

EndFunc

The expected behaviour is this: after pressing OK on "Program start", I would immediately get the dialogue "Last instruction in script" and 3 minutes after pressing the 1st OK, I would get the dialogue "Late execution" and the script would finish when I press OK on the dialogue "Late execution".

You could call this multithreading, although in this precise example, there is no risk of collision. So, would you say it is possible? You know, it is very difficult to search in a forum that something is not possible! Having an expert opinion as yours would help tremendously.

Link to comment
Share on other sites

  • Moderators

ppat,

You need to use TimerInit and TimerDiff:

MsgBox(0, "Start", "Program start")

$iBegin = TimerInit()

MsgBox(0, "Last", "Last instruction in script")

While 1
    
    If TimerDiff($iBegin) > 5000 Then display_message("Hello", "Late execution"); For 3 minutes use 1000 * 60 * 3
    
WEnd

Func display_message($title, $message)

    MsgBox(0, $title, $message)
    Exit

EndFunc

This code starts timing from pressing "OK" on the "Program start" message box. If you want to time from the "Last instruction" message box, just move the $iBegin = TimerInit() line to after the MsgBox(0, "Last", "Last instruction in script") line.

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

Try this:

MsgBox (0, "Start", "Script will start in 3 minutes")

;2 options Option 1
;Sleep (3*1000*60);3 minutes (excuse my math if it isn't correct :)
;Option 2
$timer = TimerInit ()
While 1
    If TimerDiff ($timer) >= 3*1000*60 Then
        display_message()
        ExitLoop
    Else
        Sleep (50)
    EndIf
WEnd
    
MsgBox(0, "Last", "Last instruction in script")

Func display_message ()
    MsgBox (0, "", "RAWR SAYS THE DINOSAUR!!!")
EndFunc
Link to comment
Share on other sites

I guess the closest keyword would be "timer" and I could find _Timer_SetTimer in Autoit Help file. But a handle must be passed (no handle in my case)

As long as you don't compile your script explicitly as a command-line tool there is always a gui handle to pass:

WinSetState(AutoItWinGetTitle(),'',@SW_SHOW)
MsgBox(0,'','Title: ' & AutoItWinGetTitle() & @crlf & 'hWnd: ' & WinGetHandle(AutoItWinGetTitle()))

and callback functions do not accept parameters

Define the variables to use as global or read them from within the func.

Best Regards

Edited by KaFu
Link to comment
Share on other sites

Thanks for both of your replies. It does not follow the course of events I wanted. "Last instruction in script" is not the last message.

Melba23 is getting close. The problem is that if I take more than 3 minutes to press OK on "Last instruction in script", then display_message("Hello", "Late execution") will appear after more than 3 minutes. But at least it is close. I understand now that there is no multithreading in AutoIt 3. I assume there is in Javascript by design of the language.

Anyway, although Melba23 is close, I cannot achieve what I want, because I want this:

; Main part of the program

try_something(1,2)

[Do many other instructions that may take more than 3 minutes to execute]



Func try_something($a,$b)

  if a condition is not met then 

      [Schedule a launch in 3 minutes of : try_something ($modifierd_a, $modified_b)]

      [Exit this func now and continue to process the instructions in the main part of this program]

EndFunc

Is this even possible in AutoIt3?

Link to comment
Share on other sites

MsgBox (0, "Start", "Script will start in 3 minutes")

;2 options Option 1
;Sleep (3*1000*60);3 minutes (excuse my math if it isn't correct :)
;Option 2
$timer = TimerInit ()
While 1
    If TimerDiff ($timer) >= 3000 Then; Use 3*1000*60 for 3 minutes
        $Exit = display_message()
        If $Exit Then
            ExitLoop
        Else
            $timer = TimerInit()
        EndIf
    Else
        Sleep (50)
    EndIf
WEnd
    
MsgBox(0, "Last", "Last instruction in script")

Func display_message ()
    $ret = MsgBox (4, "", "RAWR SAYS THE DINOSAUR!!!")
    If $ret = 6 Then
        $ExitTime = True
    Else
        $ExitTime = False
    EndIf
    Return $ExitTime
EndFunc

Cheers,

Brett

Link to comment
Share on other sites

  • Moderators

ppat,

That is changing the goalposts in mid-game! I hate it when people do that!

But AutoIt can still do it for you:

Global $iCounter = 0

AdlibEnable("Counter", 1000)

MsgBox(0, "Start", "Program start")

; This loop is eternal
While 1
    
    If GUIGetMsg() = - 3 Then Exit
    
WEnd

MsgBox(0, "Last", "Last instruction in script")

Exit

Func display_message($title, $message)

    MsgBox(0, $title, $message)
    Exit

EndFunc

Func Counter()
    
    $iCounter += 1
    
    If $iCounter = 10 Then   ;  use 3 * 60 for 3 minutes - this is 10 seconds
    ; stop counting
        AdlibDisable()
    ; Show message
        display_message("Hello", "Late execution")
    EndIf 
    
EndFunc

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

My code is:

MsgBox(0, "Start", "Program start")

; I would like here and instruction: "Launch display_message("Hello", "Late execution") in 3 minutes from now

MsgBox(0, "Last", "Last instruction in script")


Func display_message($title, $message)

    MsgBox(0, $title, $message)

EndFunc

The expected behaviour is this: after pressing OK on "Program start", I would immediately get the dialogue "Last instruction in script" and 3 minutes after pressing the 1st OK, I would get the dialogue "Late execution" and the script would finish when I press OK on the dialogue "Late execution".

You could call this multithreading, although in this precise example, there is no risk of collision. So, would you say it is possible? You know, it is very difficult to search in a forum that something is not possible! Having an expert opinion as yours would help tremendously.

I am testing using globals and adlib.

MsgBox(0, "Start", "Program start")
Global $message = "Foo"
Global $title = "Bar"
AdlibEnable("display_message",30*1000)

; I would like here and instruction: "Launch display_message("Hello", "Late execution") in 3 minutes from now
sleep(60*1000)
MsgBox(0, "Last", "Last instruction in script")


Func display_message()

    MsgBox(0, $title, $message)


EndFunc

It works. Sorta. The behavior is that after the initial msg, 30 seconds later the function pops. The script itself is just sleeping. I tried having the "last execution msg, but the msg seems to block the adlib message until it is dismissed. Try playing with adlib.

Bob

--------------------bobchernow, Bob ChernowWhat a long strange trip it's beenUDFs: [post="635594"]Multiple Monitor Screen Resolution Change[/post]

Link to comment
Share on other sites

Bob, M23 and Brett,

thanks for your replies. You pointed my attention to AdlibEnable, which looks promissing.

The problem in your proposals is that MsgBox(0, "Last", "Last instruction in script") always come last, after closing the message that is postponed by 3 minutes. But I want the opposite: as soon as I press "OK" in the "Start" window, all following instructions should be immediately executed. "Last instruction in script" here means that it is the last instruction in the main section of the file, but actually the last instruction to be displayed is the one that has been postponed by 3 minutes.

The help file says

"The adlib function should be kept simple as it is executed often and during this time the main script is paused. "

, but I notice that in practice, it keeps executing.

Here is the code that is closest to what I want (slightly modified from M23)

Global $iCounter = 0

MsgBox(0, "Start", "Program start")

counter()

MsgBox(0, "Last", "Last instruction in script")

; This loop is eternal
While 1
WEnd

Exit

Func display_message($title, $message)

    MsgBox(0, $title, $message)
    Exit

EndFunc

Func Counter()

    AdlibDisable()

    $iCounter += 1
    
    Sleep(2000); Simulate excuting tests for 2 seconds
        
    If $iCounter = 3 Then
   ; stop launching Counter after 3 runs
        
    ; Show message
        display_message("Hello", "Late execution")
    Else
        AdlibEnable("Counter", 2000)    ; This will run Counter again after 2 seconds
    EndIf 
    
EndFunc

This is what it does: after pressing "OK" on the start window, it launches Counter, does a few tests (simulated by the Sleep function). At 1st run, the condition is not met, so it relaunches the Counter function after 2 seconds. In the mean time, the program completes its execution ("Last instruction in script") and goes to the infinite loop. 2nd try for Counter, launched again 2 seconds after. 3rd try: this time the condition is met and says "Last execution".

Only one thing bothers me with AdlibEnable: it calls every 250 ms (or time ms) the specified "function". Is there not instead a function that calls the specified "function" only once after 250 ms (or time ms) ?

Link to comment
Share on other sites

I do not think there is one that only runs it once but you could force that by disabling the adlib function each time it runs, so it runs once and then it disables itself. Effectively that does what you want.

Bob

--------------------bobchernow, Bob ChernowWhat a long strange trip it's beenUDFs: [post="635594"]Multiple Monitor Screen Resolution Change[/post]

Link to comment
Share on other sites

One thing you have to keep in mind... msgbox() itself pauses the execution of the script! Thus if you build a timer to trigger something e.g. after 3 minutes and you have a msgbox() on screen for 5 minutes... the timer in the background keeps counting on, but the script can react earliest after the confirmation of the first msgbox(), meaning you'll get the trigger instantly after the first msgbox() is closed.

Global $timer = TimerInit()

AdlibEnable("timer")

While 1

    Switch MsgBox(3, 'Start', 'Do something' & @crlf & round((TimerDiff($timer)/1000),1))
        Case 6 ; Yes
            MsgBox(0,'', 'Task done, timer reset' & @crlf & round((TimerDiff($timer)/1000),1))
            $timer = TimerInit()
        Case 7 ; No
            MsgBox(0,'', 'Task not done, timer not reset' & @crlf & round((TimerDiff($timer)/1000),1))
        Case Else ; 2 = Cancel... and everything else
            ExitLoop
    EndSwitch
    
    sleep(10)

WEnd

MsgBox(0, "Last", "Last instruction in script")

Func Timer()
    If TimerDiff($timer) > 10000 Then
        MsgBox(0, '', 'Fallen asleep?')
        $timer = TimerInit()
    EndIf
EndFunc   ;==>timer

If you want to utilize msgbox() AND want to have triggered an event while old msgbox() is still open... write timestamp to ini-file and use a second (background) script to monitor that ini-file and pop-up a reminder.

Link to comment
Share on other sites

  • Moderators

ppat,

You have again changed those goal posts in mid-match.

If I understand correctly (which given the earlier attempts seems unlikely!), you want to run a number of commands between "Program start" and "Last instruction in script" - then, when this finishes, wait until a specified time before running the "Late execution" code. Nothing else need happen between "Last instruction in script" and the "Late execution" code. However, if the "Program start" to "Last instruction in script" takes longer than the specified time, you want the "Late execution" code to run anyway at that point and then return to the "Program start" to "Last instruction in script" code to finish it.

If that is what you want then this will do that for you:

Global $iCounter = 0
Global $fEnded = False
Global $fLate_Ended = False

AdlibEnable("Counter", 1000)

MsgBox(0, "Start", "Program start")

Sleep(20 * 1000) ; sleep to sumulate the code here

MsgBox(0, "Last", "Last instruction in script")

If $fLate_Ended Then Exit

$fEnded = True

; This loop is eternal
While 1
    Sleep(100)
WEnd

Func display_message($title, $message)

    MsgBox(0, $title, $message)
    If $fEnded Then Exit

EndFunc

Func Counter()
    
    $iCounter += 1
    
    If $iCounter = 10 Then  ;  use 3 * 60 for 3 minutes - this is 10 seconds
   ; stop counting
        AdlibDisable()
   ; Show message
        display_message("Hello", "Late execution")
        $fLate_Ended = True
    EndIf 
    
EndFunc

Alter the value in the Sleep command and you will see that script only ends when BOTH the "Program start" to "Last instruction in script" code AND the "Late execution" code have finished.

I hope I have understood correctly - but change the goal-posts again and you are on your own my friend! ;-)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

Thank you all, I now have an answer to my question. The key was AdlibEnable which schedules a launch of a function repetitively at a certain frequency until AdlibDisable is called. To achieve sort of "parallel threads", I wrap up the code in an au3 file and execute this file from the main code which is in an other au3 file. The main file continues to execute, while the sub file waits for the late execution, in parallel.

Thanks, subject closed.

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...