VB.NET Timer Beispiel
Inhaltsverzeichnis
- 1 VB.NET Timer Beispiel – Code im Intervall ausführen
- 2 5 verschiedene Timer – VB.NET Timer Beispiel
- 3 VB.NET Timer Beispiel – Das Timer Steuerelement
- 4 VB.NET Timer Beispiel – Vorstellung beendet
- 5 Tickst du noch ganz richtig?
- 6 ++ Update 02.12.21 ++
- 7 Downloads – VB.NET Timer Beispiel
VB.NET Timer Beispiel – Code im Intervall ausführen
In diesem Beitrag zeige ich ein einfach zu verstehendes VB.NET Timer Beispiel.
Vor allem bei Anfängern ist der Timer ein sehr beliebtes Steuerelement, da er einmal auf die Form gezogen, sehr einfach mit Code zu versehen ist.
Es gibt allerdings auch beim einfachen Timer-Steuerelement einige Sachen zu beachten, sonst stehen eventuell Kopfschmerzen bevor.
Wer sich bereits mit dem Timer an sich auskennt, aber zum Beispiel Schwierigkeiten hat, den Timer zur Laufzeit zu erstellen und mit Code zu versehen, kann sich diesen Beitrag anschauen.
Der Zweck des Timers
Die Frage, die man sich vermutlich zuerst stellt, ist, welchen Sinn ein Timer überhaupt hat und warum man ein Control dafür braucht?
Code im Intervall ausführen
Jeder kommt in seinem Programmierer-Dasein glaube ich an den Punkt, dass er Code Intervall-basiert ausführen möchte.
Das heißt also, dass ein gewisser Code-Block immer wieder, aber mit gewissen Pausen dazwischen ausgeführt werden soll.
Anders gesagt: Ich möchte meinen Code timen – höhö 😉 und suche nach der passenden Möglichkeit!
Die erste Anlaufstelle, die man finden wird, ist der Timer aus dem „System.Windows.Forms„-Namespace.
Das ist auch der Timer, der sich standardmäßig in der Steuerelemente-Toolbox befindet und daher vermutlich der Ausgangspunkt.
Code nach einer gewissen Zeit ausführen
Eine andere Funktionsweise, Welche häufig analog zum Timer ergoogelt wird, ist die Ausführung von Code nach einer gewissen Zeit.
Man könnte zum Beispiel nach dem Start des Programmes wollen, dass es 5 Sekunden danach einen Ping an einen Server sendet.
Oder man möchte vielleicht mit gewissem Zeit-Verzug die aktuelle Versionsnummer der Applikation ziehen.
Sicherlich gibt es heutzutage – mit dem modernen NET Framework – „bessere“ Alternativen als einen Timer, jedoch..
Neulinge stoßen auch heute noch immer wieder auf Diese, oder ähnliche Problemstellungen und somit auf den Timer.
So ging es mir in meiner Anfangszeit natürlich auch..
5 verschiedene Timer – VB.NET Timer Beispiel
Wenn man nun durch Recherche die ersten paar Forenbeiträge gefunden hat, werden einem mehr oder weniger hier und da auch anderen Klassen auffallen.
Wer tiefer forscht wird – jedenfalls mir bekannt – 5 Timer im .NET Framework von Microsoft finden.
Ja richtig gehört, es sind ganze fünf, uff!
Die verschiedenen Timer
Der Vollständigkeit halber, liste ich Diese hier gerne alle auf:
System.Windows.Forms.Timer
System.Timers.Timer
System.Threading.Timer
System.Web.UI.Timer
System.Windows.Threading.DispatcherTimer
Letztendlich geht es in diesem Beitrag allerdings primär um den folgenden, „normalen“ Timer.
Lass Dich also bitte vor allem als Anfänger nicht von den anderen möglichen Timern einschüchtern, bzw. verwirren!
System.Windows.Forms.Timer
VB.NET Timer Beispiel – Das Timer Steuerelement
Schauen wir uns nun nach dem Intro-Gerede 😉 das Timer-Control mal genauer an.
Konstruktoren
Das Timer-Steuerelement hat 2 verschiedene Konstruktoren:
new()
Einmal den leeren Konstruktor, dementsprechend ohne Parameter.
new(container)
Und als nächstes den Konstruktor mit einem Parameter namens Container. Um die ganze Sache nicht unnötig zu verkomplizieren, ist diese Überladung des Konstruktors einfach nur dazu da, den Timer mit einem Container zu assoziieren. Dies geschieht zum Beispiel im Hintergrund, wenn der Timer aus der Toolbox auf die Form gezogen wird. Dazu kann man sich auch gut den Designer-Code der Form einmal anschauen, aber Vorsicht, nichts kaputtmachen!
Me.Timer1 = New System.Windows.Forms.Timer(Me.components)
Eigenschaften / Properties
Folgende Eigenschaften hat der Timer zu bieten
Name
Das ist natürlich eine mehr oder weniger Standard-Eigenschaft. Mit diesem Namen spricht man den Timer nachher im Code an.
Enabled
Dieser Wert gibt an, ob der Timer gerade „läuft„, also ob er gerade sein Tick-Ereignis im angegebenen Intervall signalisieren und wiederholen soll. Hat praktisch den gleichen Effekt wie die nachfolgenden Methoden.
Interval
Mit der Interval-Property legen wir fest, bzw. rufen wir ab, in welcher Frequenz der Timer tickt, also seinen Code abarbeitet. Standardmäßig steht der Wert auf 100 Millisekunden. Einen Tipp den ich mal vor ewigen Zeiten gelesen habe ist, das Intervall des Timers nicht unter 18ms zu stellen, da das menschliche Auge wohl eh nichts darunter wahrnehmen kann – ob’s stimmt, keine Ahnung 😊. Jedenfalls wenn wir irgendwas visuell „Timern“ wollen.
GenerateMember
Auch eine – ich würde sagen – Standardeigenschaft für Steuerelemente aus dem .NET Framework. Wenn die Eigenschaft auf False steht, kann man im Code nicht auf das jeweilige Control zugreifen. Habe ich zugegebenermaßen noch nie dran rumgespielt und noch nie jemanden erlebt, der das getan hat. Hört sich für Controls die eben nicht angesprochen werden müssen sinnvoll und ressourcenschonender an. Ich denke mir allerdings auch, dass den Fehler kaum ein anderer Programmierer so schnell finden würde. Wer denkt in dem Moment daran, wenn man plötzlich ein Control nicht ansprechen kann.
Modifiers
Damit kann man den Zugriff, bzw. die Sichtbarkeit des Controls bestimmen. Standardmäßig steht Sie auf Friend. Friend aus VB.NET entspricht dem internal-Modifizierer aus C# und bedeutet, dass man das Element aus der selben Assembly aus erreichen kann. Braucht man eigentlich nicht wirklich anfassen..
Tag
Diese Eigenschaft bietet die Möglichkeit benutzerdefinierte Daten an das Objekt zu knüpfen. So viel jedenfalls zur komplizierten Beschreibung aus Visual Studio. Einfach gesagt: Du kannst eine eigene Klasse erstellen, instanziieren und dem Tag des Controls zuweisen. So kannst du dann später wieder auf die Daten zugreifen, indem du diese natürlich wieder in den richtigen Typ castest und mit dem Getter aus der Eigenschaft herausholst.
Methoden
Hier gehe ich auf die wichtigen, jedoch nicht auf alle Methoden des Timers ein.
Start
Startet den Timer und hat praktisch den selben Effekt, wie die Enabled-Eigenschaft auf True zu setzen.
Stop
Stoppt den Timer und hat praktisch den selben Effekt, wie die Enabled-Eigenschaft auf False zu setzen.
Ereignisse
Tick
„Tick“ ist das wichtigste Ereignis des Timers, also wo eigentlich alles seinen Lauf nimmt. Dieses Ereignis wird im angegebenen Intervall aufgerufen und bietet uns so die Möglichkeit, Code wiederholend aufzurufen – auf dem UI-Thread.
VB.NET Timer Beispiel – Vorstellung beendet
Beispielcode – Los geht’s
Nachdem ich das Timer-Steuerelement nun schon ein wenig detaillierter dargestellt habe und man nun wichtige Eigenschaften, Methoden, usw. kennt, können wir loslegen 🤓.
Fallbeispiel – Digitale Uhr
In unserem VB.NET Timer Beispiel werden wir es mal versuchen, eine kleine digitale Uhr darzustellen.
Der erste Gedanke ist ggf. Folgender: „Okay, ich muss also jede Sekunde, die aktuelle Uhrzeit anzeigen„.
Schauen wir uns das Ganze mal an:
Timer auf die Form ziehen
Um mit dem VB.NET Timer Beispiel zu beginnen, musst du ein Timer-Steuerelement auf die Form ziehen. Wundere dich jedoch nicht, dass das Control im Gegensatz zu einem Button z. B. nicht direkt auf der Form auftaucht.
Stattdessen positioniert sich der Timer unterhalb der Form und in einem gesonderten Bereich:
Wann geht es los?
Zuerst müssen wir uns Gedanken machen, wann der Timer immer zuschlagen, also den Code ausführen soll.
In unserem Beispiel könnten wir daher sagen: Jede Sekunde, richtig? Nope, leider nicht!
Wieso nicht? Ich versuche es mit meinen außerordentlichen Paint Skills – löl – zu verdeutlichen:
Wir erinnern uns ans gute Versteckspielen aus der Kindheit! Derjenige der zählt, hat das ungefähr so gemacht
Er hat bei 1 begonnen (der erste Tick), dann hat er 1 Sekunde gewartet und bei 2 weiter gemacht, wieder eine Sekunde gewartet, 3, usw..
Nunja, aber nur weil unser Zähler in diesem Rhythmus begonnen hat zu zählen, heißt das jedoch nicht, dass es synchron mit der tatsächlichen Zeit ist.
Dabei spielt neben dem eigenen Rhythmus natürlich auch der Start-Zeitpunkt eine wesentliche Rolle.
Wenn unsere Computer-Uhr zum Beispiel einen Sekunden-Sprung macht, heißt das nicht, dass auch wir diesen Sprung beim Zählen in diesem Moment machen.
Das kann daran liegen, dass wir eventuell erst wenige Millisekunden vorher begonnen haben zu zählen.
Nachdem der Timer nun schon „auf der Form“ ist und wir einen möglichen Fallstrick verstanden haben, können wir anfangen zu coden.
Das Intervall des Timers sollte für die Uhr also auf dem Standardwert von 100ms ausreichen.
Das Tick-Ereignis mit Code versehen
Fügen wir nun den Code hinzu, der die Uhrzeit z. B. in einem Label anzeigt, daher das Label zur Form hinzuzufügen nicht vergessen!
Ich habe den Timer1 noch in etwas Passenderes, also z. B. tmrTime unbenannt und das Label passend lblTime genannt.
Private Sub tmrTime_Tick(sender As Object, e As EventArgs) Handles tmrTime.Tick lblTime.Text = DateTime.Now.ToString("HH:mm:ss") End Sub
Let’s Debug – VB.NET Timer Beispiel
Starte das Programm nun mit F5, bzw. mit dem Play-Knopf, oben in der Mitte in Visual Studio.
Und? Was passiert!? Nichts, haha 😂.
Vergiss nicht, den Timer in z. B. dem „Form-Load“-Ereignis (z. B. Doppelklick auf die Form selbst) durch tmrTime.Start() zu starten.
Alternativ kannst du den Timer natürlich auch standardmäßig laufen lassen, indem du im Designer die Timer-Eigenschaft „Enabled“ auf True setzt.
Fertig – So sieht die digitale Uhr z. B. aus
Hier ein animiertes Bild von meiner digitalen Timer Uhr:
Tickst du noch ganz richtig?
Ich kann mich noch zu gut an ein bestimmtes Problem erinnern, Welches ich als Anfänger hatte.
Zeit floß in die Recherche und der Code wurde mehrfach überprüft, bis ich dann endlich fündig wurde..
Ich hatte eine Synchronisation eines Terminkalenders gebaut und stieß dort auf das Problem.
Timer Arbeitsaufgabe Beispiel
Die Aufgabe – Terminkalender Synchronisation
Tja da stand ich damals bei meiner ersten Anstellung und sollte die Aufgabe erledigen, die Termine eines Kalenders zu synchronisieren.
Den Kalender an sich hatte ich schon – relativ mühelos – gebaut, nachfolgend ging es also nur noch um die Auflistung der Termine darin.
Auch dies stellte rein vom Code her kein Problem für mich dar, bis..
Die Synchronisations-Schleife
Da natürlich – wie immer – alles schnell gehen musste, nahm ich *zack* einen Timer zur Hand, zog ihn auf die jeweilige Form und fing an im Tick-Ereignishandler in die Tastatur zu hacken.
Ein paar Datenbank-Abfragen hier, ein paar Gruppierungen da, zum Schluss noch ein paar Schleifen und das Ding stand.
Nur ein komischer Bug war da..
Der Timer „überlappte“
Das war nachher der Ursprung des Fehlers. Die Verarbeitung der Daten dauerte länger, als das Intervall des Timers dieser Verarbeitung bis zur nächsten Ausführung Zeit gab – verdammt!
Lösung A:
Den Timer so lange pausieren, wie der Tick-Handler zum Abarbeiten der Daten benötigt.
Lösung B:
Den Intervall des Timers hochdrehen.
Lösung C:
Ein anderes Werkzeug wie z. B. Async/Await verwenden.
Meine (damalige) Entscheidung
Aufgrund der Schnelligkeit (da ich es auswendig wusste), habe ich zur Async/Await-Variante gewechselt.
Ich habe den Timer also durch eine Async Sub (geht bei EventHandlern leider nicht anders) ersetzt, welche Ihre Arbeit dann durch eine Schleife im inneren, im Intervall ausführte.
Die schlechteste Variante
Die schlechteste Option wäre vermutlich Lösung B, denn sobald die Arbeitslast durch mehr Daten wächst, könnte man eventuell wieder vor dem gleichen Problem stehen.
Die optimale Entscheidung
Die damals optimalste Lösung wäre vermutlich die Option A gewesen. Dadurch hätte man lediglich wenige Zeilen ergänzen müssen: Shame on me!
Private Sub TheTimer_Tick(sender As Object, e As EventArgs) Handles TheTimer.Tick ' use this, or talk to the timer directly.. Dim timer = CType(sender, Timer) ' stop the timer directly TheTimer.Stop(); ' Data operations.. ' start the timer again.. TheTimer.Start() End Sub
Fallbeispiel – Code nach Zeit ausführen
Im nächsten kleinen Timer-Abschnitt beschäftigen wir uns noch ein wenig mit einem weiteren Fallbeispiel.
Einige Zeit nach dem ursprünglichen Erscheinen des Beitrages ist mir aufgefallen, dass ich noch ein wichtiges Anwendungsbeispiel vergessen habe.
Dabei geht es um die einmalige Ausführung eines Code-Block nach einer gewissen Verzögerung, wie z. B. „mache xy nach 5 Sekunden„.
Ziehe dafür einfach einen Timer auf die Form und packe folgenden Code (z. B. durch Doppelklick auf den Timer) in den Ereignishandler des Tick-Ereignisses:
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick ' the code to be executed on each tick End Sub
private void Timer1_Tick(object sender, EventArgs e) { // the code to be executed on each tick }
Beachte dabei, dass Du – falls Du C# verwenden solltest – auch auf die Verknüpfung des Handlers zum Ereignis achten musst.
In VB.NET passiert dies oben durch die „Handles-Klausel„, oder durch eine getrennte Anweisung mit Hilfe von „AddHandler“.
In C# ist dies hingegen eine getrennte Anweisung im Designer-Code:
// somewhere in the designer code Timer1.Tick += Timer1_Tick;
Falls Du den Handler durch den Doppelklick auf den Timer erstellt hast, solltest Du Dir im ersten Schritt über Obiges keine Sorgen machen müssen.
Visual Studio erstellt die jeweiligen Methoden und die Verknüpfungen zwischen Ereignis und Methode automatisch.
Im nächsten Schritt kannst Du die „Enabled„-Eigenschaft des Timers nun im Designer auf „True“ stellen.
Das würde den Timer direkt beim Starten der Form (falls gewünscht) automatisch ausführen.
Ansonsten kannst Du den Timer natürlich auch durch die entsprechende Methode namens „Start„, zu jeder Zeit manuell starten.
Achte dabei auf ein passendes Intervall, wie z. B. „5000“ (in Millisekunden) für 5 Sekunden.
Damit der Code letztendlich nur einmal ausgeführt wird, stoppen wir den Timer sofort beim ersten (und dadurch einzigen) Aufruf des Tick-Ereignishandlers.
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick Timer1.Stop() ' do your thing End Sub
private void Timer1_Tick(object sender, EventArgs e) { Timer1.Stop(); // do your thing }
Anschließend kannst Du dann den eigentlichen Code ausführen lassen und falls Du möchtest, den Timer auch später erneut aufrufen.
Schaue Dir allerdings unbedingt final an, wie man es mit modernen Framework-Mitteln stattdessen umsetzen könnte.
Zum Thema asynchrone Programmierung habe ich im entsprechenden Beitrag geschrieben.
++ Update 02.12.21 ++
Im letzten Update des Beitrages habe ich ein weiteres Beispiel für den Timer und die dazugehörigen Bilder hinzugefügt.
Besonders interessant wird vermutlich auch die Ausführung von Code nach einiger Zeit sein.
Daher habe ich mich dann letztendlich dazu entschieden hier noch einmal ein wenig nachzuarbeiten.