Timer nacheinander ausführen

  • VB.NET

Es gibt 15 Antworten in diesem Thema. Der letzte Beitrag () ist von wolfi_bayern.

    Timer nacheinander ausführen

    Hallo Zusammen,

    die Seite hat mir die letzten Tage extrem weitergeholfen, da ich nach ein paar Jahren Pause mich erst wieder reinfuchsen musste.
    Ich schreibe zur Zeit ein Programm, um ein variables Byte-Array über einen SerialPort zu schicken, zeitabhängig natürlich. Das Programm steht soweit auch schon, es hängt nur leider an der Zeitsteuerung.

    Ich hab meine Problem mal vereinfach in einem Programm dargestellt.

    Visual Basic-Quellcode

    1. Public Class Form1
    2. Dim counter As Integer
    3. Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    4. If counter >= 100 Then
    5. Timer1.Enabled = False
    6. counter = 0
    7. Else
    8. counter = counter + 1
    9. Label1.Text = counter.ToString
    10. End If
    11. End Sub
    12. Private Sub Timer2_Tick(sender As Object, e As EventArgs) Handles Timer2.Tick
    13. If counter >= 10 Then
    14. Timer2.Enabled = False
    15. counter = 0
    16. Else
    17. counter = counter + 1
    18. Label1.Text = counter.ToString
    19. End If
    20. End Sub
    21. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    22. counter = 0
    23. Timer1.Enabled = True
    24. Timer2.Enabled = True
    25. End Sub
    26. End Class


    Ich will einen Button drücken, der dann verschiedene Timer startet, allerdings will ich das Timer1 erst zu Ende läuft und dann Timer2 startet. Zur Zeit laufen noch beide Parallel.
    Ich habe es mit einer "Do..Loop"-Anweisung innerhalb des Timers probiert. Allerdings wird da das Timer-Intervall nicht berücksichtigt.
    Hat da jemand eine Idee oder einen anderen Lösungsansatz um Anweisungen zeitlich nacheinander zu starten, also wie:
    Button-->10 min eine Anweisung-->20 min gleiche Anweisung mit anderen Variablen-->10 min.. usw.

    Achja, bevor ich es vergesse, ich programmiere VB in Visual Studio Express 2013.

    Danke euch schon einmal im Voraus :)
    Alexus


    --> Hat sich erledigt.
    Manchmal ist die Lösung so einfach, bin allerdings selber erst nach Verfassen des Posts darauf gekommen.

    Nur, wen es noch interessiert:

    Visual Basic-Quellcode

    1. Public Class Form1
    2. Dim counter As Integer
    3. Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    4. If counter >= 100 Then
    5. Timer1.Enabled = False
    6. counter = 0
    7. Timer2.Enabled = True
    8. Else
    9. counter = counter + 1
    10. Label1.Text = counter.ToString
    11. End If
    12. End Sub
    13. Private Sub Timer2_Tick(sender As Object, e As EventArgs) Handles Timer2.Tick
    14. If counter >= 10 Then
    15. Timer2.Enabled = False
    16. counter = 0
    17. Else
    18. counter = counter + 1
    19. Label1.Text = counter.ToString
    20. End If
    21. End Sub
    22. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    23. counter = 0
    24. Timer1.Enabled = True
    25. End Sub
    26. End Class


    Bin allerdings immer noch offen für elegantere Lösungen :)

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Alexus“ ()

    Wenn du eine bestimmte Anzahl an Iterationen wünschst, kannst du auch eine for-Schleife verwenden:

    VB.NET-Quellcode

    1. For i = 1 to 100
    2. lblCounter.Text = i.toString()
    3. ''' Dein Code
    4. Next
    5. For j = 1 to 10
    6. lblCounter.Text = i.toString()
    7. ''' Dein Code
    8. Next
    9. For k = 1 to 100 Step 5 ''' Mit Step lassen sich auch Schritte angeben
    10. ''' Bla
    11. Next


    Und ein Tipp am Rande: Benenne deine Controls nach ihren Aufgaben, bei vielen Label1, Label2, usw. wird die ganze Sache irgendwann unübersichtlich, und wenn du deinen Code mal veröffentlichst, erkennt keiner welches Label etc. was tut.

    Grüße
    Grüße
    Felix
    Solange der Thread an erster Stelle ist, gebe ich auch einen kleinen Tipp:

    Kommentiere deinen Code. Besonders, wenn du kaum mehr etwas weißt. So kannst du die Prozedur von deinem Code mitverfolgen. Du hättest schneller sehen können, dass eine WENN Abfrage für "Wenn dies/das passiert" steht.

    Dennoch freut es mich selber immer wieder, wenn ihr selber auf die Lösung kommt. Ich habe immer solch komplizierte Geschichten. Viel Glück weiterhin!

    //P.s
    @Kenaex
    Wird bei einer Forschleife die Form nicht unresponsive?
    Wenn ich eine Frage stelle, habe ich sie bereits gegooglet. Ja, es kommt vor, dass ich die Antwort übersehe. Ja, es kommt vor, dass ich sie nicht verstehe. Deshalb bin ich hier. Wenn dies eure Frage war, dann antwortet bitte nicht. Es stiehlt sämtliche Motivation.
    @Alexus Willkommen im Forum. :thumbup:
    Was haben die Timer und Co mit dem SerialPort zu tun?
    Dort gibt es Methoden, ganze Byte-Arrays zu übertragen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @Sekki Bei einer ​for-Schleife fehlt nur ein Intervall, wenn man für ein Intervall ​Threading.Thread.Sleep() verwendet, wird die Form nicht mehr "ansprechbar", weil der Thread ja "schläft". An sich gibt es da aber keine Probleme.

    Grüße
    Grüße
    Felix
    @Kenaex & @Sekki jaein. 100 mal ne kleine Berechnung ausführen sieht zwar der User nicht (vielleicht nen winzigen Ruckler, wenn er das Fenster genau dann verschiebt) doch der Thread ist durch diese Berechnung blockiert, die MessageQueue wird so lange nicht weiter abgearbeitet, bis diese Berechnung fertig ist.
    Man kann auch, als extrembeispiel, mithilfe von for 10 mal die letzte Ziffer von Pi berechnen lassen. Bis du 10-mal bis unendlich gezählt hast ist der Rechner immer noch nicht fertig damit, und die Gui solange eingefroren.
    Nicht umsonst wurden die ganzen Async() Methoden und async/await eingeführt. Alles das erleichtert es einem Arbeit vom GUI-Thread entweder Konkurrent laufen zu lassen (Berechnung und GUI bekommen im selben Thread abwechselnd Zeit) oder auf andere Threads auszulagern.
    Vielen Dank für euren schnellen Antworten.

    @Kanaex: Ich habe eine for-Schleife auch schon in Erwägung gezogen, aber mir fehlt da die Bestimmbarkeit der Zeit. Also nach dem Motto: Führe den Befehl alle 100ms aus und das Ganze für 60 min.
    In meinem Hauptprogramm hab ich die relevanten Labels und Boxen schon benannt, keine Sorge ;) Ich wollte euch nur nicht mit meinem kompletten Code erschlagen, deswegen habe ich ein kleines Beispiel verfasst.

    @Sekki: Du hast ja Recht, um es für euch verständlicher zu machen und um später selber besser durchzusteigen, sollte man alles durchkommentieren.

    @RodFromGermany: Vielen Dank für deine Begrüßung bei euch im Forum. Wie schon weiter oben erwähnt, war das nur ein kleines Beispiel für meine eigentliches Problem.
    Im richtigen Programm verwende ich die Timer um regelmäßig Befehle an einen Serial Port zu schicken, um nicht in den Timeout zu kommen.

    @ErfinderDesRades: Ich brauche die Timer nicht um unterschiedliche Frequenzen darzustellen, sondern um verschiedene Gesamtzeiten zu haben, z.B.: timer1: alle 100ms für 30 min, danach timer2: alle 100ms für 40 min, usw.
    Bei mir kommt noch dazu, dass jeder Timer dazu noch unterschiedliche variable Bytes in ein Array schreiben muss. Byte(5-7) ändern sich bei mir. timer1: (5)=1; (6)=2; (7)=3; timer2: (5)=3;(6)=2;(7)=1, aber alle Timer schicken das gleiche Array, nur variabel. Mir fällt nur leider keine Lösung ein, dass mit einem Timer zu lösen, außer vlt mit einer State Maschine.

    Kann mir bitte mal einer verraten, wie ich @nickname als Erwähnung bei meinen Antworten hinbekomme? Würde euch gerne persönlich ansprechen^.^

    Im Moment habe ich das Problem, dass ich über meinen Serial Port dauerhaft etwas abfragen möchte, ohne das mein Programm blockiert ist. Ob ich noch einen Timer verwenden sollte? ?(
    @Alexus Dein Code sieht mir nicht danach aus, als hätte das mit Deinem eigentlichen Problem zu tun.
    Beschreibe doch mal Dein eigentliches Problem. ;)
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Mein eigentliches Problem konnte ich zum Glück schon lösen und mein Programm läuft mittlerweile. Ich stelle gerne mal den Code zur Verfügung, ist halt ein paar Zeilen länger.

    Im Moment habe ich das Problem, dass ich eine Funktion mit Hilfe eines Timers löse, aber ich, wenn ich die Variable so setze, dass der Timer eine Stunde laufen soll, er eine Stunde und 5 min läuft.
    Hier mal mein Code-Schnipsel vom Timer: (es ist nicht nur speziell bei dem Timer so, sondern bei Jedem)

    Kann ich das Problem irgendwie ausgleichen?

    Visual Basic-Quellcode

    1. Private Sub Timer5_Tick(sender As Object, e As EventArgs) Handles Timer5.Tick
    2. 'Das Eingabefeld für die Drehzahl optisch auf aktiv setzen
    3. dreh5.BackColor = Color.Green
    4. 'Eine If-Absicherung, falls das Feld leer sein sollte.
    5. If time5.Text = "" Then
    6. time5.Text = 0
    7. End If
    8. 'Variablen Werte zuweisen
    9. bte(5) = ssignal5 - Fix(ssignal5 / 256) * 256
    10. bte(6) = Fix(ssignal5 / 256)
    11. summe = 33 + 7 + 83 + 1 + 170 + (ssignal5 - Fix(ssignal5 / 256) * 256) + Fix(ssignal5 / 256)
    12. bte(7) = summe - Fix(summe / 256) * 256
    13. 'Die if-Abfrage für den Timer, der nach einer gewissen Zeit abgeschaltet werden soll und zum
    14. 'nächsten Timer wechseln soll. Timer.Intervall = 100ms
    15. 'Beispiel: time5.text= 60 --> 60*600=36000s --> 36000s * 0,1s(Timer-Intervall) = 3600s=1h
    16. If counter >= time5.Text * 600 Then
    17. Timer5.Enabled = False
    18. dreh5.BackColor = Color.Red
    19. counter = 0
    20. Timer6.Enabled = True
    21. Else
    22. counter = counter + 1
    23. sls.Write(bte, 0, 8)
    24. End If
    25. End Sub

    Alexus schrieb:

    VB.NET-Quellcode

    1. time5.Text = 0
    Gib Deinem Projekt Option Strict On, beseitige die Fehler und danach beschreibe, was Dein Programm machen soll und was es tatsächlich macht.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ich hab mal die Option Strict On gemacht --> 91 Error-Meldungen später :D

    Meine Timer.Tick Funktion sollte nach eingestellten Variablen 60 Sekunden laufen, aber läuft 5,5 sec/60 sec länger. Sowas summiert sich, bei 60 min sind das schon 5,5 min.

    Die Messung habe ich manuell vorgenommen und würde mein Umrechnungsfaktor anpassen, dass der Fehler vernachlässigbar wird.
    Jetzt ist meine Frage, woher kommt diese zusätzliche Zeit? Kann man die schon von vornherein umgehen? Dass der Timer wirklich nur 60 sec ausgeführt wird und keine 65?

    Visual Basic-Quellcode

    1. Private Sub Timer5_Tick(sender As Object, e As EventArgs) Handles Timer5.Tick
    2. 'Das Eingabefeld für die Drehzahl optisch auf aktiv setzen
    3. dreh5.BackColor = Color.Green
    4. 'Eine If-Absicherung, falls das Feld leer sein sollte.
    5. If time5.Text = "" Then
    6. time5.Text = CStr(0)
    7. End If
    8. 'Variablen Werte zuweisen
    9. bte(5) = CByte(ssignal5 - Fix(ssignal5 / 256) * 256)
    10. bte(6) = CByte(Fix(ssignal5 / 256))
    11. summe = CStr(33 + 7 + 83 + 1 + 170 + (ssignal5 - Fix(ssignal5 / 256) * 256) + Fix(ssignal5 / 256))
    12. bte(7) = CByte(CDbl(summe) - Fix(CDbl(summe) / 256) * 256)
    13. 'Die if-Abfrage für den Timer, der nach einer gewissen Zeit abgeschaltet werden soll und zum
    14. 'nächsten Timer wechseln soll. Timer.Intervall = 100ms
    15. 'Beispiel: time5.text= 60 --> 60*600=36000s --> 36000s * 0,1s(Timer-Intervall) = 3600s=1h
    16. If counter >= CDbl(time5.Text) * 600 Then
    17. Timer5.Enabled = False
    18. dreh5.BackColor = Color.Red
    19. counter = 0
    20. Timer6.Enabled = True
    21. Else
    22. counter = counter + 1
    23. sls.Write(bte, 0, 8)
    24. End If
    25. End Sub

    Alexus schrieb:

    aber läuft 5,5 sec/60 sec länger

    Alexus schrieb:

    VB.NET-Quellcode

    1. Timer5.Enabled = False
    Klar, wenn Du den Timer anhältst und wieder startest.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Alexus schrieb:

    Timer5.Enabled = False



    dreh5.BackColor = Color.Red



    counter = 0



    Timer6.Enabled = True


    Wo schalte ich den denn wieder ein? Da kommt doch schon der nächste Timer. Timer 5 wird hier ausgeschaltet und Timer 6 eingeschaltet.

    Alexus schrieb:

    Wo schalte ich den denn wieder ein?
    Sorry, meine Glaskugel ist leider bei der Reparatur.
    Überlege Dir, wozu Du denn mehrere Timer benötigst. Einer sollte es auch tun.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!