SetTimerEx(Period, Func, Params*)

Post your working scripts, libraries and tools for AHK v1.1 and older
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

SetTimerEx(Period, Func, Params*)

05 Feb 2014, 05:14

SetTimerEx(Period, Func, Params*)

Similar to SetTimer, but calls a function, optionally with one or more parameters.

I wrote this in August 2011, but have just updated it to work with v2 (and v1.1).

Code: Select all

SetTimerEx(period, func, params*)
{
    static s_timers, s_next_tick, s_timer, s_index, s_max_index
    
    if !s_timers  ; Init timers array and ensure script is #persistent.
        s_timers := Object(), n:="OnMessage",%n%(0)
    
    if (func = "!") ; Internal use.
    {
        ; This is a workaround for the timer-tick sub not being able to see itself
        ; in v2 (since it is local to the function, which is not running).
        SetTimer timer-tick, % period
        return
    }
    
    if !IsFunc(func)
        return
    
    ; Create a timer.
    timer           := {base: {stop: "Timer_Stop"}}
    timer.run_once  := period < 0
    timer.period    := period := Abs(period)
    timer.next_run  := next_run := A_TickCount + period
    timer.func      := func
    timer.params    := params
    
    ; If the timer is not set to run before next_run, set it:
    if (!s_next_tick || s_next_tick > next_run)
    {
        s_next_tick := next_run
        SetTimer timer-tick, % -period
    }
    
    return s_timers.Insert(timer) ? timer : 0
    
timer-tick:
    s_next_tick := "X" ; greater than any number
    s_index := 1
    While s_timer := s_timers[s_index]
    {
        if (s_timer.next_run <= A_TickCount)
        {
            if s_timer.next_run  ; Timer has not been disabled.
            {
                ; Update next run time before calling func in case it takes a while.
                s_timer.next_run := s_timer.run_once ? "" : A_TickCount + s_timer.period
                ; Call function.
                static s_f
                s_f := s_timer.func, %s_f%(s_timer.params*)
            }
            if !s_timer.next_run  ; Timer was run-once (disabled above) or previously disabled.
            {
                ; Remove both our references to this timer:
                s_timers._Remove(s_index)
                s_timer := ""
                ; Continue without incrementing s_index.
                continue
            }
        }
        ; Determine when the next timer should fire.
        if (s_next_tick > s_timer.next_run)
            s_next_tick := s_timer.next_run
        s_index += 1
    }
    s_timer := ""
    ; Set main timer for next sub-timer which should be fired, if any.
    if (s_next_tick != "X")
        SetTimerEx(s_next_tick > A_TickCount ? A_TickCount-s_next_tick : -1, "!")
    return
}

Timer_Stop(timer) {
    timer.next_run := 0
}
Example:

Code: Select all

t1 := SetTimerEx(1000, "SoundTimer", "*-1")
Sleep, 500
t2 := SetTimerEx(1000, "SoundTimer", "*16")
SoundTimer(param) {
    SoundPlay % param
    ToolTip % param
}

~Esc::  ; Press Esc to
t1.stop()  ; stop the timer,
Sleep 3000  ; wait 3 seconds,
ExitApp  ; then exit.
Guest10
Posts: 578
Joined: 01 Oct 2013, 02:50

Re: SetTimerEx(Period, Func, Params*)

05 Feb 2014, 08:03

great, test and would like to know if i could use this instead of native SetTimer in ALL cases?
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: SetTimerEx(Period, Func, Params*)

06 Feb 2014, 00:16

You can use this and a function instead of native SetTimer and a label. You can't use this with a label.
Guest10
Posts: 578
Joined: 01 Oct 2013, 02:50

Re: SetTimerEx(Period, Func, Params*)

09 May 2014, 10:38

i had totally forgotten about this honorable script. what are main advantages of using this function over the simpler (native) version? :ugeek:
User avatar
joedf
Posts: 8953
Joined: 29 Sep 2013, 17:08
Location: Canada
Contact:

Re: SetTimerEx(Period, Func, Params*)

09 May 2014, 14:48

Namespace
Image Image Image Image Image
Windows 10 x64 Professional, Intel i5-8500, NVIDIA GTX 1060 6GB, 2x16GB Kingston FURY Beast - DDR4 3200 MHz | [About Me] | [About the AHK Foundation] | [Courses on AutoHotkey]
[ASPDM - StdLib Distribution] | [Qonsole - Quake-like console emulator] | [LibCon - Autohotkey Console Library]
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: SetTimerEx(Period, Func, Params*)

10 May 2014, 02:19

I assume joedf means that you can avoid using global variables. That's a minor point.

You can set an unlimited number of timers to call the same code/function, since you can pass parameters. For instance, if you were monitoring multiple windows, you could set a timer for each window (and have them firing at different times/repeating at different rates).
User avatar
joedf
Posts: 8953
Joined: 29 Sep 2013, 17:08
Location: Canada
Contact:

Re: SetTimerEx(Period, Func, Params*)

10 May 2014, 06:49

Oh good point, i didnt think of that one... Multiple timers for one function.. Cool! :P
Image Image Image Image Image
Windows 10 x64 Professional, Intel i5-8500, NVIDIA GTX 1060 6GB, 2x16GB Kingston FURY Beast - DDR4 3200 MHz | [About Me] | [About the AHK Foundation] | [Courses on AutoHotkey]
[ASPDM - StdLib Distribution] | [Qonsole - Quake-like console emulator] | [LibCon - Autohotkey Console Library]
arcticir
Posts: 694
Joined: 17 Nov 2013, 11:32

Re: SetTimerEx(Period, Func, Params*)

12 May 2014, 21:17

Based AHK-H
face two problems:
1 h_Self itself object
2 Z_FX()


Code: Select all

; F1:=FTimer(100, "t",1)
; F2:=FTimer(200, "t",2)
; FTimer(F1)		Close F1
; FTimer(0,"t")		Close ALL t()


FTimer(ByRef s, m:="",j*){	; hy ; Timed function: Time Name Parameter
	static f:=[],y:=[]
	if IsObject(s)
	{
		if s.4
		{
			SetTimer % "FTimer" s.4, Off
			f.Remove(s.4),y[s.1].Remove(s.4)
			for i,n in y[s.1]
				Break
			i?"":y.Remove(s.1),s:=""

		}
	}
	else if !s
	{
		for i,n in y.Remove(m)
		{
			SetTimer % "FTimer" i, Off
			i:=f.Remove(i)
			Loop 4
			i.Remove()
		}
	}
	else if m
	{
		Loop
			if f[p:="_" A_Index] ? "" : (f[p]:=[m,j,s,p],(IsObject(y[m])?y[m]:y[m]:=[]).Insert(p,""))
				break
		if !IsLabel("FTimer" p)
			h_Self.addScript("FTimer" p ":`nFTimer(""" p """)`nReturn",0)
		SetTimer % "FTimer" p, % s
		Return f[p]
	}
	else
	{
		if ((z_fx(f[s].1, f[s].2*) = "/\") or (f[s].3 < 0))
		{
			SetTimer % "FTimer" s,Off
			p:=f.Remove(s),y[p.1].Remove(s)
			for i,n in y[p.1]
				Break
			i?"":y.Remove(p.1)
			Loop 4
			p.Remove()

		}
	}
}
Last edited by arcticir on 13 May 2014, 10:16, edited 6 times in total.
ozzii
Posts: 481
Joined: 30 Oct 2013, 06:04

Re: SetTimerEx(Period, Func, Params*)

13 May 2014, 01:43

@arcticir
Sorry for the question, but what's a H-based version?
arcticir
Posts: 694
Joined: 17 Nov 2013, 11:32

Re: SetTimerEx(Period, Func, Params*)

13 May 2014, 04:17

Is the need to use AHKH.EXE
ozzii
Posts: 481
Joined: 30 Oct 2013, 06:04

Re: SetTimerEx(Period, Func, Params*)

14 May 2014, 01:29

Me I'm using the file from ahkscript.org

Is the H better than the one I'm using ?
User avatar
joedf
Posts: 8953
Joined: 29 Sep 2013, 17:08
Location: Canada
Contact:

Re: SetTimerEx(Period, Func, Params*)

14 May 2014, 07:32

No H is for other "special things", Just stick with your current version of autohotkey.
If you didn't know about it, then you probably don't need it. The main advantages are Multithreading & "Intergrating" autohotkey in other languages.
Image Image Image Image Image
Windows 10 x64 Professional, Intel i5-8500, NVIDIA GTX 1060 6GB, 2x16GB Kingston FURY Beast - DDR4 3200 MHz | [About Me] | [About the AHK Foundation] | [Courses on AutoHotkey]
[ASPDM - StdLib Distribution] | [Qonsole - Quake-like console emulator] | [LibCon - Autohotkey Console Library]
ozzii
Posts: 481
Joined: 30 Oct 2013, 06:04

Re: SetTimerEx(Period, Func, Params*)

15 May 2014, 03:13

OK, I will stick with mine.
arcticir
Posts: 694
Joined: 17 Nov 2013, 11:32

Re: SetTimerEx(Period, Func, Params*)

22 Sep 2014, 08:03

Hi, lexikos

This example why only pop up a MsgBox?

Code: Select all

#Persistent
SetTimerEx(-200, "c", 1)
SetTimerEx(-250, "c", 2)
Return

a:
c(1)
Return

b:
c(2)
Return

c(d){
MsgBox % d
Sleep, 20000
}

And this example will pop up two:

Code: Select all

#Persistent
SetTimer a, -200
SetTimer b, -250

Return
a:
c(1)
Return

b:
c(2)
Return
c(d){
MsgBox % d
Sleep, 20000
}
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: SetTimerEx(Period, Func, Params*)

22 Sep 2014, 22:19

SetTimerEx uses its own timer subroutine internally, which does not return until your timer function returns. Until it returns, no more timers can execute.

Btw,
Because timers operate by temporarily interrupting the script's current activity, their subroutines should be kept short (so that they finish quickly) whenever a long interruption would be undesirable.
guest3456
Posts: 3463
Joined: 09 Oct 2013, 10:31

Re: SetTimerEx(Period, Func, Params*)

22 Sep 2014, 22:22

i think HotKeyIt also created one of these scripts, using the SetTimer() msdn function

lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: SetTimerEx(Period, Func, Params*)

23 Sep 2014, 01:20

You might mean this one. Setting a Win32 timer for each script timer is a bit of overkill. The limitation of SetTimerEx could be removed by replacing the one use of AutoHotkey's SetTimer with one Win32 SetTimer. Alternatively, one could add PostMessage/OnMessage to allow multiple threads without making the Thread Interrupt or Thread NoTimers settings ineffective.
arcticir
Posts: 694
Joined: 17 Nov 2013, 11:32

Re: SetTimerEx(Period, Func, Params*)

23 Sep 2014, 07:58

Thanks.
I am looking to improve this function.

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: No registered users and 125 guests