Causes a subroutine to be launched automatically and repeatedly at a specified time interval.

SetTimer, Label [, Period|On|Off, Priority]



Label The name of the label or hotkey label to which to jump, which causes the commands beneath Label to be executed until a Return or Exit is encountered. As with the parameters of almost all other commands, Label can be a variable reference such as %MyLabel%, in which case the name stored in the variable is used as the target.

On: Re-enables a previously disabled timer at its former period. If the timer doesn't exist, it is created (with a default period of 250).

Off: Disables an existing timer.

Period: Creates or updates a timer using this parameter as the number of milliseconds that must pass since the last time the Label subroutine was started. When this amount of time has passed, Label will be run again (unless it is still running from the last time). The timer will be automatically enabled. To prevent this, call the command a second time immediately afterward, specifying OFF for this parameter.

If this parameter is blank and:
1) the timer does not exist: it will be created with a period of 250.
2) the timer already exists: it will be enabled and reset at its former period unless a Priority is specified.


This optional parameter is an integer between -2147483648 and 2147483647 (or an expression) to indicate this timer's thread priority. If omitted, 0 will be used. See Threads for details.

To change the priority of an existing timer without affecting it in any other way, leave the parameter before this one blank.



Timers are useful because they run asynchronously, meaning that they will run at the specified frequency (interval) even when the script is waiting for a window, displaying a dialog, or busy with another task. Examples of their many uses include taking some action when the user becomes idle (as reflected by %A_TimeIdle%) or closing unwanted windows the moment they appear.

Although timers may give the illusion that the script is performing more than one task simultaneously, this is not the case. Instead, timed subroutines are treated just like other threads: they can interrupt or be interrupted by another thread, such as a hotkey subroutine. See Threads for details.

Whenever a timer is enabled, re-enabled, or updated with a new period, it will not run right away; its time period must expire first. If you wish the timer's first execution to be immediate, use the Gosub command immediately after the SetTimer command.

Similarly, if SetTimer is used on an existing timer and parameter #2 is a number or the word ON, the timer's internal "time of last run" will be reset to the current time; in other words, the entirety of its period must elapse before it will run again. An easy way to reset a timer is to omit all parameters except the first. For example: SetTimer, TimerName. However, in versions prior to 1.0.31, attempting to reset a timer within its own subroutine/thread has no effect.

Currently, timers cannot run much more often than every 10ms on Windows XP/2000/NT and about 55ms on Windows 9x. Specifying a Period less than this will usually result in an actual interval of 10 or 55 (but this behavior may change in future versions so shouldn't be relied upon).

Timers with very short periods might not be able to run as often as expected if the current setting of SetBatchLines restricts the speed of the script too much. Similarly, if the total number of lines to be executed in all timed subroutines is large, you may need to alter SetBatchLines to allow them to run as often as specified.

In addition, a timer might not be able to run as often as specified under the following conditions:

  1. Other applications are putting a heavy load on the CPU.
  2. The timer subroutine itself takes longer than its own period to run, or there are too many other competing timers (altering SetBatchLines may help).
  3. The timer has been interrupted by another thread, namely another timed subroutine, hotkey subroutine, or custom menu item. If this happens and the interrupting thread takes a long time to finish, the interrupted timer will be effectively disabled for the duration. However, any other timers will continue to run by interrupting the thread that interrupted the first timer.
  4. The script is uninterruptible as a result of Critical or Thread Interrupt/Priority. During such times, timers will not run. Later, when the script becomes interruptible again, any overdue timer will run once as soon as possible and then resume its normal schedule.

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.

Timers that stay in effect for the duration of a script should usually be created in the auto-execute section. By contrast, a temporary timer might often be disabled by its own subroutine (see examples at the bottom).

Whenever a timed subroutine is run, it starts off fresh with the default values for settings such as SetKeyDelay. These defaults can be changed in the auto-execute section.

Although timers will operate when the script is suspended, they will not run if the current thread has "Thread NoTimers" in effect or whenever any thread is paused. In addition, they do not operate when the user is navigating through the tray icon menu or the main window's menu.

If hotkey response time is crucial (such as in games) and the script contains any timers whose subroutines take longer than about 5 ms to execute, use the following command to avoid any chance of a 15 ms delay. Such a delay would otherwise happen if a hotkey is pressed at the exact moment a timer thread is in its period of uninterruptibility:
Thread, interrupt, 0 ; Make all threads always-interruptible.

If a timer is disabled while its subroutine is currently running, that subroutine will continue until it completes.

The KeyHistory feature shows how many timers exist and how many are currently enabled.

In v1.0.36.03+, a timer's period can be no larger than 4294967295 milliseconds (49.7 days). In earlier versions, the limit is 2147483647 milliseconds (24.8 days).

To keep a script running -- such as one that contains only timers -- use #Persistent.



Gosub, Return, Threads, Thread (command), Critical, IsLabel(), Menu, #Persistent



; Example #1: Close unwanted windows whenever they appear:
SetTimer, CloseMailWarnings, 250

WinClose, Microsoft Outlook, A timeout occured while communicating
WinClose, Microsoft Outlook, A connection to the server could not be established

; Example #2: Wait for a certain window to appear and then alert the user: #Persistent SetTimer, Alert1, 500 return Alert1: IfWinNotExist, Video Conversion, Process Complete return ; Otherwise: SetTimer, Alert1, Off ; i.e. the timer turns itself off here. SplashTextOn, , , The video conversion is finished. Sleep, 3000 SplashTextOff return
; Example #3: Detection of single, double, and triple-presses of a hotkey. This ; allows a hotkey to perform a different operation depending on how many times ; you press it: #c:: if winc_presses > 0 ; SetTimer already started, so we log the keypress instead. { winc_presses += 1 return } ; Otherwise, this is the first press of a new series. Set count to 1 and start ; the timer: winc_presses = 1 SetTimer, KeyWinC, 400 ; Wait for more presses within a 400 millisecond window. return KeyWinC: SetTimer, KeyWinC, off if winc_presses = 1 ; The key was pressed once. { Run, m:\ ; Open a folder. } else if winc_presses = 2 ; The key was pressed twice. { Run, m:\multimedia ; Open a different folder. } else if winc_presses > 2 { MsgBox, Three or more clicks detected. } ; Regardless of which action above was triggered, reset the count to ; prepare for the next series of presses: winc_presses = 0 return