16. Timer

Timer erlauben es, einen Actionhandler in bestimmten Zeitabständen automatisch aufzurufen. Man kann sich das so vorstellen, als ob jemand einen Button in regelmäßigen Abständen drückt. Damit kann man beispielsweise eine blinkende Schrift realisieren, eine Spielfigur über das Spielfeld bewegen oder eine Uhr weiterzählen.

Die Routine TimerStart aktiviert einen Timer. Sie erwartet den Namen des Actionhandlers, der aufgerufen werden soll, sowie einen oder zwei numerische Werte. Der erste Wert gibt an, wie lange es dauern soll, bis der Timer das erste Mal auslöst. Die Zeitangabe erfolgt in "tics", das sind 1/60s. Der zweite Wert gibt das Zeitintervall an, in dem der Timer danach periodisch auslösen soll (ebenfalls in tics). Wird der zweite Wert nicht angegeben oder ist er Null, so löst der Timer nur genau einmal aus (Single-Shot Timer). Das maximale Zeitintervall beträgt jeweils 65535 tics, das entspricht etwa 18 Minuten.

Um einen Timer zu stoppen verwenden Sie TimerStop. Single-Shot Timer brauchen nicht gestoppt zu werden. Es ist ein guter Stil alle Timer am Programmende, vorzugsweise im OnExit-Handler, zu stoppen. Sollten Sie das vergessen stoppt das System die aktiven Timer.

Wenn ein Timer auslöst erzeugt er ein BASIC-Event, das wie allen anderen Events (Aktivieren eines Button, Klick in eine Liste usw.) behandelt wird. Das bedeutet:

  • Timerevents unterbrechen laufende Actionhandler nicht. Das Timerevent wird erst behandelt, wenn der laufende Actionhandler beendet ist.

  • Timerevents haben keine erhöhte Priorität. Sie reihen sich wie jedes andere Ereignis in der Ereigniswarteschlage hinten ein.
Bei sehr schnellen Timern kann es vorkommen, dass der Timer bereits wieder auslöst, bevor das letzte Timerevent behandelt wurde. Damit diese Situation nicht zu einem Überlaufen der Warteschlange führt, stellt der Eventmanager sicher, dass sich für jeden Timer maximal ein Event in der Warteschlage befindet. Zu schnell aufeinander folgende Events werden verworfen.

Verwechseln Sie Timerevents nicht mit den Befehlen Delay und Pause! Delay und Pause unterbrechen die Abarbeitung eines Handlers für eine bestimmte Zeit während Timer einen eigenen Handler aufrufen.

TimerStart

TimerStart aktiviert einen Timer. Das kann eine einmaliger Timer (Single-Shot-Timer) oder ein periodischer Timer sein.
Syntax: <th> = TimerStart ( <Handler>, tics1 [, tics2] )

<th>: Variable vom Typ HANDLE. Der Wert wird für TimerStop benötigt.

<Handler>: Name des ActionHandlers, der vom Timer aufgerufen werden soll.
Er muss als TimerAction deklariert sein.

tics1: Zeit, bis der Timer erstmalig auslöst (in 1/60s)

tics2: Intervall (in 1/60s), in dem der Timer periodisch auslösen soll.
Wird tics2 nicht angegeben (oder wenn er Null ist) löst der Timer nur einmal aus (Single-Shot-Timer).

Erlaubte Werte für tics1 und tics2: 0 ... 65535


TimerStop

TimerStop hält einen Timer an. Es erwartet das Handle, das von TimerStart zurückgegeben wurde. Es ist explizit erlaubt:
  • Einen Timer zu stoppen, der bereits gestoppt wurde.

  • Einen Single-Shot-Timer zu stoppen, der bereits ausgelöst hat.


Hinweis: TimerStop entfernt keine Timerevents aus der Warteschlange. Falls sich beim Aufruf von TimerStop noch ein Timerevent in der Warteschlange befindet, so wird dieses noch ausgeführt.


Syntax: TimerStop <th>

<th>: Handle, das von TimerStart geliefert wurde



TimerAction

Actionhandler, die von einem Timer aufgerufen werden, müssen als TimerAction deklariert sein.

Tabelle

Der Parameter "sender" enthält das Application-Objekt des Programms, der Parameter "actionData" ist unbenutzt und enthält den Wert Null.

Beispiele. Den folgenden Code finden Sie komplette im R-BASIC Beispiel "Datum und Zeit\TimerDemo".

Beispiel 1: Blinkende Schrift

Eine globale Variable z bestimmt, ob die Schrift gezeigt wird oder nicht. Das TimerHandle th ist ebenfalls global, damit wir dem Timer wieder anhalten können.

DIM z
DIM th as HANDLE


Mit TimerStart aktivieren wir die blinkende Schrift. Der erste Timerevent soll sofort ausgelöst werden (zweiter Parameter ist Null), dann soll der Timer alle 0,5 Sekunden auslösen (dritter Parameter: 30 tics).

th = TimerStart (TimerBlink, 0, 30)


TimerStop schaltet die blinkende Schrift wieder aus. Wir kümmern uns nicht darum, ob die Schrift gerade zu sehen ist oder nicht.

TimerStop th


Der eigentliche TimerHandler prüft die globale Variable z. Ist sie ungleich Null wird dein Leertext ausgegeben und z auf Null gesetzt. Beim nächsten Handleraufruf ist z dann Null und der Text selbst wird ausgegeben. z wird auf 1 gesetzt.

TIMERACTION TimerBlink

  IF z THEN
    Print at 3, 5; "                  "
    z = 0
  ELSE
    print at 3, 5;"R-BASIC Timer Demo"
    z = 1
  End IF

END ACTION


Beispiel 2: Willkommensbox

Viele Programme zeigen am Start eine Infobox an, die dann von allein wieder verschwindet. Dafür eignet sich ein Single-Shot-Timer. Im OnStartup-Handler öffnen wir die Dilaogbox und starten den Timer. Das Timerhandle th2 wird bei Single-Shot-Timern nicht weiter gebraucht.

SYSTEMACTION DemoStartupHandler
  DemoStartupDialog.Open
  th2 = TimerStart ( StartupTimerHandler, 180)  ' 3 sek.
END ACTION


Der Timerhandler muss nur die Dilaogbox schließen.

TIMERACTION StartupTimerHandler
  DemoStartupDialog.Close
END ACTION


Die Dialogbox selbst sollte das Attribut DA_HIDDEN_UNTIL_OPENED gesetzt haben, damit das System keinen Button erzeugt, mit dem man die Dialogbox manuell öffnen kann. Die Anweisung "modal = APP_MODAL" ist auskommentiert. Sie würde bewirken, dass der Nutzer nicht mit dem Programm interagieren kann, solange die Dialogbox noch offen ist.

Dialog DemoStartupDialog
  Caption$ = "Willkommen!"
  Children = TimerStartupText
  attrs = DA_HIDDEN_UNTIL_OPENED
  'modal = APP_MODAL
End OBJECT

Tipps & Tricks

  • Actionhandler vom Typ TimerAction sind kompatibel mit dem Typ ButtonAction. Das heißt, Sie können einem Button einen Timer-Handler als ActionHandler zuweisen und so ihren Timerhandler komfortabel testen. In diesem Fall wird der Parameter "actionData" mit dem actionData-Wert des Buttons belegt.

  • Der zwei- oder mehrmalige Aufruf von TimerStop mit dem gleichen TimerHandle oder mit einem Null-Handle (leeres Handle) ist erlaubt. Sie können deshalb in Ihrem OnExit-Handler einfach sämtliche Timer stoppen (Aufruf von TimerStop), egal ob die Timer noch laufen oder ob sie je benutzt wurden (unbenutzte Handles sind leere Handles).

^

Weiter...