Lässt eine Subroutine automatisch und wiederholt in einem angegebenen Zeitintervall laufen.
SetTimer , Label, PeriodeOnOffDelete, Priorität
Name des Labels oder Hotkey-Labels, der angesprungen werden soll, um die Befehle unterhalb von Label auszuführen, bis ein Return oder Exit erreicht wurde. Label kann, wie die meisten Parameter von anderen Befehlen auch, eine Variablenreferenz wie %MeinLabel% sein, um den Inhalt der Variable als Ziel zu verwenden.
[v1.1.01+]: Lässt man Label weg, wird standardmäßig A_ThisLabel verwendet. Zum Beispiel könnte SetTimer,, Off
innerhalb einer Timer-Subroutine verwendet werden, um den Timer zu deaktivieren. SetTimer,, 1000
wiederum würde entweder die Periode des aktuellen Timers ändern oder einen neuen Timer mit dem Label der aktuell laufenden Subroutine erstellen. [v1.1.24+]: Wenn A_ThisLabel leer ist, aber der aktuelle Thread durch einen Timer gestartet wurde, wird dieser Timer verwendet. Das ist besonders für Timer nützlich, die Funktionen oder Funktionsobjekte starten müssen.
[v1.1.20+]: Wenn es kein gültiger Labelname ist, kann dieser Parameter der Name einer Funktion sein, deren Parameterliste keine Pflichtparameter aufweist (siehe Funktionsbeispiel), oder eine einzelne Variablenreferenz mit einem Funktionsobjekt. Zum Beispiel SetTimer %FunkObj%, 1000
oder SetTimer % FunkObj, 1000
. Andere Ausdrücke, die Objekte zurückgeben, werden zurzeit nicht unterstützt. Mehr dazu finden Sie im Beispiel weiter unten.
Hinweis: [v1.1.24+]: Die Übergabe einer leeren Variable oder eines Ausdrucks, der einen leeren Wert ergibt, wird als Fehler eingestuft. Dieser Parameter muss entweder einen nicht-leeren Wert enthalten oder komplett weggelassen werden.
On: Reaktiviert einen zuvor deaktivierten Timer mit seiner früheren Periode. Falls der Timer noch nicht vorhanden ist, wird er erstellt (mit einer Standardperiode von 250). Der Timer wird außerdem zurückgesetzt. Wenn ein Timer bereits vorhanden ist, der zuvor im Nur-Einmal-Laufen-Modus gestartet wurde, wird er auch dieses Mal nur einmal ausgeführt.
Off: Deaktiviert einen vorhandenen Timer.
Delete [v1.1.20+]: Deaktiviert und entfernt einen vorhandenen Timer. Wenn der Timer mit einem Funktionsobjekt verbunden ist, wird das Objekt freigegeben. Nur das Ausschalten eines Timers wird das Objekt nicht freigeben.
Periode: Erstellt oder aktualisiert einen Timer. Der absolute Wert von diesem Parameter ist die ungefähre Zeit in Millisekunden, die ablaufen muss, bevor der Timer ausgeführt wird. Der Timer wird dabei automatisch aktiviert und zurückgesetzt. Man kann den Timer so einstellen, dass er sich automatisch wiederholt oder nur einmal läuft:
[v1.0.46.16+]: Wenn Periode negativ ist, wird der Timer nur einmal laufen. Zum Beispiel würde -100 den Timer nach 100 ms einmal ausführen und ihn dann deaktivieren, als hätte man SetTimer, Label, Off
angegeben.
[v1.1.24+]: Wenn Label ein via Skript erstelltes Objekt ist (also keine Funktion oder Label), wird der Timer automatisch gelöscht, nachdem die Timer-Funktion ihren Wert zurückgegeben hat, es sei denn, der Timer wurde wieder aktiviert. Dadurch kann das Objekt freigegeben werden, wenn es vom Skript nicht länger benötigt wird, aber das bedeutet auch, dass die Periode und Priorität des Timers verworfen werden.
Periode muss ein Integer sein, es sei denn, es wird eine Variable oder ein Ausdruck genutzt, dann werden alle Nachkommastellen ignoriert. Dessen absoluter Wert darf nicht größer als 4294967295 ms (49,7 Tage) sein.
Standardwert: Wenn dieser Parameter leer ist und:
1) der Timer nicht existiert, wird er mit einer Periode von 250 erstellt.
2) der Timer bereits existiert, wird er aktiviert und auf seine frühere Periode zurückgesetzt, sofern keine Priorität angegeben ist.
Dieser optionale Parameter ist ein Integer zwischen -2147483648 und 2147483647 (oder ein Ausdruck), um die Thread-Priorität des Timers zu bestimmen. Lässt man diesen Parameter weg, wird standardmäßig 0 verwendet. Siehe Threads für weitere Details.
Um die Priorität eines vorhandenen Timers zu ändern, ohne ihn anderweitig zu beeinflussen, lassen Sie den Parameter vor diesem leer.
Timer sind nützlich, weil sie asynchron laufen - das heißt, dass sie in einem bestimmten Intervall (Frequenz) ausgeführt werden, auch dann, wenn das Skript auf ein Fenster wartet, ein Dialogfenster anzeigt oder mit einer anderen Aufgabe beschäftigt ist. Unter anderem kann der Timer verwendet werden, um eine Aktion bei Abwesenheit des Benutzers durchzuführen (in Verbindung mit A_TimeIdle) oder um unerwünschte Fenster sofort wieder zu schließen, wenn sie erscheinen.
Timer erzeugen nur die Illusion, dass das Skript mehrere Aufgaben gleichzeitig durchführen kann. In Wirklichkeit werden zeitgesteuerte Subroutinen genauso wie andere Threads behandelt: sie können unterbrechen oder von anderen Threads, wie z. B. eine Hotkey-Subroutine, unterbrochen werden. Siehe Threads für weitere Details.
Die Subroutine eines erstellten, reaktivierten oder mit einer neuen Periode versehenen Timers wird nicht sofort ausgeführt; zuerst muss seine angegebene Periode verstreichen. Wenn der Timer sofort beginnen soll, müssen Sie Gosub zum Ausführen der Timer-Subroutine verwenden (allerdings wird das keinen neuen Thread starten, wie es der Timer selbst machen würde; demzufolge werden Einstellungen wie SendMode nicht mit ihren Standardwerten beginnen).
Zurücksetzen: Wenn SetTimer auf einen bereits vorhandenen Timer angewendet wird und der 2. Parameter eine Nummer oder das Wort ON ist (oder weggelassen wird), wird der Timer zurückgesetzt; das heißt, dass seine Periode einmal komplett ablaufen muss, bevor seine Subroutine erneut starten kann.
Genauigkeit des Timers: Durch die Granularität (Ungenauigkeit) der Zeiterfassung im Betriebssystem wird Periode möglicherweise auf das nächstmögliche Vielfache von 10 oder 15.6 Millisekunden aufgerundet (abhängig vom Typ der installierten Hardware und Treiber). In Windows 2000/XP ist eine Periode von 1 bis 10 äquivalent zu 10 oder 15.6. Eine kürzere Verzögerung kann mittels Loop+Sleep erreicht werden, wie bei DllCall+timeBeginPeriod+Sleep gezeigt.
Zuverlässigkeit: Es kann sein, dass ein Timer nicht zum erwarteten Zeitpunkt ausgeführt wird, wenn folgende Bedingungen auftreten:
Timer funktionieren zwar, wenn das Skript suspendiert ist, aber nicht, wenn Thread NoTimers im aktuellen Thread vorhanden ist oder wenn ein Thread pausiert wurde. Darüber hinaus werden sie nicht funktionieren, wenn der Benutzer in einem der Skriptmenüs navigiert (wie z. B. das Tray-Menü oder eine Menüleiste).
Da Timer vorübergehend die aktuelle Aktivität des Skripts unterbrechen, sollten ihre Subroutinen kurzgehalten werden (so dass sie schnell zum Ende kommen), wann immer eine lange Unterbrechung unerwünscht ist.
Sonstige Bemerkungen: Timer, die die ganze Zeit laufen sollen, sollten üblicherweise im automatischen Ausführungsbereich erstellt werden. Dagegen deaktivieren sich temporäre Timer oft mit ihren eigenen Subroutinen (siehe Beispiele weiter unten).
Jede via SetTimer gestartete Subroutine verwendet vorerst die Standardwerte von Einstellungen wie SendMode. Diese Standardwerte können im automatischen Ausführungsbereich geändert werden.
Wenn die Hotkey-Reaktionszeit von entscheidender Bedeutung ist (z. B. bei Videospielen) und das Skript bestimmte Timer enthält, deren Subroutinen länger als 5 ms zum Ausführen benötigen, dann sollte der folgende Befehl verwendet werden, um eine mögliche Verzögerung von 15 ms zu unterbinden. So eine Verzögerung würde ansonsten auftreten, wenn ein Hotkey exakt zu dem Zeitpunkt gedrückt wird, wo ein Timer-Thread in seiner unterbrechungsfreien Phase ist:
Thread, interrupt, 0 ; Macht alle Threads jederzeit unterbrechbar.
Deaktiviert man einen Timer, während seine Subroutine noch läuft, wird diese Subroutine bis zu ihrem Ende fortgesetzt.
Die KeyHistory-Funktion zeigt, wie viele Timer vorhanden und wie viele zurzeit aktiviert sind.
Um ein Skript dauerhaft laufen zu lassen -- z. B. ein Skript, das ausschließlich Timer enthält -- ist es erforderlich, #Persistent zu verwenden.
Gosub, Return, Threads, Thread (Befehl), Critical, IsLabel(), Menu, #Persistent
Schließt unerwünschte Fenster, sobald sie erscheinen.
#Persistent SetTimer, MailWarnungenSchließen, 250 return MailWarnungenSchließen: WinClose, Microsoft Outlook, Während der Kommunikation mit dem Server wurde das Zeitlimit überschritten WinClose, Microsoft Outlook, Es konnte keine Verbindung aufgebaut werden return
Wartet auf ein bestimmtes Fenster und alarmiert danach den Benutzer.
#Persistent SetTimer, Alarm1, 500 return Alarm1: if not WinExist("Video-Konvertierung", "Prozess abgeschlossen") return ; Ansonsten: SetTimer, Alarm1, Off ; d. h. der Timer deaktiviert sich selbst. SplashTextOn, , , Die Video-Konvertierung wurde abgeschlossen. Sleep, 3000 SplashTextOff return
Erkennt, ob ein Hotkey einmal, zweimal oder dreimal gedrückt wurde. Dadurch kann ein Hotkey eine unterschiedliche Operation durchführen, je nachdem, wie oft er gedrückt wurde.
#c:: if (winc_eingaben > 0) ; Da SetTimer bereits gestartet wurde, wird stattdessen der Tastendruck protokolliert. { winc_eingaben += 1 return } ; Ansonsten ist das der erste Tastendruck einer neuen Serie. Zählung wird ; auf 1 gesetzt und der Timer gestartet: winc_eingaben := 1 SetTimer, TasteWinC, -400 ; Wartet auf weitere Eingaben innerhalb eines 400-Millisekunden-Zeitfensters. return TasteWinC: if (winc_eingaben = 1) ; Die Taste wurde einmal gedrückt. { Run, m:\ ; Öffnet einen Ordner. } else if (winc_eingaben = 2) ; Die Taste wurde zweimal gedrückt. { Run, m:\multimedia ; Öffnet einen anderen Ordner. } else if (winc_eingaben > 2) { MsgBox, Drei oder mehr Klicks erkannt. } ; Unabhängig von der zuvor ausgelösten Aktion wird die Zählung zurückgesetzt, ; um die nächste Serie von Tastendrücken vorzubereiten: winc_eingaben := 0 return
Ein einfacher Zähler. Verwendet eine Funktion als Timer-Subroutine.
#Persistent SetTimer, Tick, 1000 Tick() { static count := 0 ToolTip % count++ }
Ein komplexerer Zähler. Verwendet eine Methode als Timer-Subroutine.
counter := new SecondCounter counter.Start() Sleep 5000 counter.Stop() Sleep 2000 ; Eine Beispiel-Klasse zum Zählen der Sekunden... class SecondCounter { __New() { this.interval := 1000 this.count := 0 ; Tick() hat einen impliziten Parameter "this", der eine Referenz auf ; das Objekt ist, daher müssen wir eine Funktion erstellen, die ; "this" und die aufzurufende Methode voneinander trennt: this.timer := ObjBindMethod(this, "Tick") } Start() { ; Bekannte Einschränkung: SetTimer benötigt eine reine Variablenreferenz. timer := this.timer SetTimer % timer, % this.interval ToolTip % "Counter gestartet" } Stop() { ; Um den Timer auszuschalten, müssen wir dasselbe Objekt erneut übergeben: timer := this.timer SetTimer % timer, Off ToolTip % "Counter stoppt bei " this.count } ; In diesem Beispiel ruft der Timer diese Methode auf: Tick() { ToolTip % ++this.count } }
Tipps bezüglich des oberen Beispiels:
this.timer := this.Tick.Bind(this)
verwenden. Wenn this.timer
aufgerufen wird, wird es tatsächlich this.Tick.Call(this)
aufrufen (außer dass this.Tick
nicht neu berechnet wird). ObjBindMethod() hingegen erzeugt ein Objekt, das this.Tick()
aufruft.this
direkt verwenden, anstelle von this.timer
. Dadurch kann man temporäre Variablen vermeiden. Allerdings kann ObjBindMethod() auch nützlich sein, wenn das Objekt mehrere Methoden hat, die von verschiedenen Ereignisquellen wie Hotkeys, Menüpunkte, GUI-Steuerelemente aufgerufen werden sollen.timer
im obigen Beispiel).