2 Schleifen parallel ohne Threading und Main Procedure??

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 4 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    2 Schleifen parallel ohne Threading und Main Procedure??

    Hallo!

    Ich versuche ein Programm für eine Druckkalibration zu entwickeln. Dafür muss ich ständig ein Digitales Multimeter (DMM) über seriellen Anschluss abfragen und er schickt mir eine Spannung zurück, mit der ich einen Strom berechne. Bis da alles gut, aber jetzt muss das Programm wenn ein Benutzer auf ein CheckBox clickt, ständig (so lange das CheckBox geklickt ist) ein 2. Gerät abfragen.

    Mein Problem ist, dass ich nicht hinkriege, es nur durch Ereignisse zu programmieren. Wenn ich eine Sub Main habe dann ist alles kein Problem, (Abfrage 1 DMM -- IF Checkbox -- frag 2. DMM) außer das der Programm evtl. zu lange braucht um die ganze Prozedur zu durchlaufen und der Messwert des 1. Gerätes stimmt nicht mehr.

    Gibt es einen Weg es durch Ereignisse zu realisieren? Wenn ich die Abfragen z.B in FormLoad stelle, da es eine endlose Schleife ist, zeigt das Programm die Form gar nicht. Wenn ich es aber beim CheckboxChecked reintue, dann reagiert das erste Mal, fällt aber wieder in der endlose Schleife der Abfrage und dann reagiert das Programm nicht wieder auf das Ereignis CheckBocChecked.

    Sozusagen brauch ich ein Ereigniss der etwa "Solange die Apllication läuft tu das" und solange CheckBoxChecked tu noch das dazu".

    Besser wäre noch wenn ich PARALLEL beide serielle Schnittstellen ansprechen konnte, so dass ich GLEICHZEITIG beide Geräte abfragen kann.

    Letzte Frage: Kann man Timers in .Net irgendwie miteinander synchronisieren, so dass sie exakt ticken???

    Danke im Voraus :)
    Life doesn't give you a datasheet. Sometimes the docs are wrong and you have to try it.
    Schau mal hier rein, da ging es um parallele Schleifen:
    Parallel.ForEach / zwei Schleifen machbar?!?
    "Gib einem Mann einen Fisch und du ernährst ihn für einen Tag. Lehre einen Mann zu fischen und du ernährst ihn für sein Leben."

    Wie debugge ich richtig? => Debuggen, Fehler finden und beseitigen
    Wie man VisualStudio nutzt? => VisualStudio richtig nutzen
    Naja, Parallel.ForEach würde auch bei zwei Endlosschleifen den GUI Thread blockieren, da der Thread auf die Beendigung/Rückgabe des ForEach wartet.
    Die Option mit einem System.Timers.Timer (nicht System.Windows.Forms.Timer), denke ich ist da die bessere. Hier einfach über ein Boolean-Feld ein Flag bauen, das im Timer.Tick (oder Elapsed) Event abfragen und eben bei True auch das zweite Gerät abfragen. Ansonsten wird nur das erste Gerät beim Ablauf des Intervalls abgefragt.

    Alternativ könnte man die beiden Endlosschleifen per Async/Await so verpacken, dass der GUI-Thread nicht mehr blockiert, doch Endlosschleifen sind IMHO nicht das beste Programmiermodell.
    Halte den Eventhandler und den UI-Thread frei von komplexer Logik. Das garantiert dir zum einen eine schnelle Bearbeitung der Events und zum anderen, dass das UI nicht einfriert. SerialPort.DataReceived läuft bereits in (je) einem Arbeitssthread. Vorschlag:

    VB.NET-Quellcode

    1. Private _flag As Boolean
    2. Private _qdata As New BlockingCollection(Of Packet)
    3. Private Sub CheckBox1_CheckedChanged(sender As Object, e As EventArgs) Handles cb.CheckedChanged
    4. _flag = DirectCast(sender, CheckBox).Checked
    5. End Sub
    6. Private Sub SerialPort_DataReceived(sender As Object, e As SerialDataReceivedEventArgs) Handles sp1.DataReceived, sp2.DataReceived
    7. Dim data As String = String.Empty
    8. Dim index As Int32 = 0
    9. Dim sp As SerialPort = DirectCast(sender, SerialPort)
    10. If sp Is sp1 Then
    11. data = sp.ReadExisting()
    12. index = 1
    13. ElseIf _flag AndAlso sp Is sp2 Then
    14. data = sp.ReadExisting()
    15. index = 2
    16. End If
    17. If String.IsNullOrEmpty(data) Then Return
    18. Dim p As New Packet
    19. p.Data = data
    20. p.Time = Date.Now ' or HPET via QueryPerformanceCounter()
    21. p.Index = index
    22. _qdata.Add(p)
    23. End Sub
    24. Private Sub Worker()
    25. Dim p As Packet
    26. While True
    27. p = _qdata.Take()
    28. ' p.Time = Empfangszeitpunkt
    29. ' p.Data = Daten
    30. ' p.Index = Datenquelle
    31. ' Use data
    32. End While
    33. End Sub

    mit dieser Klasse "Packet":

    VB.NET-Quellcode

    1. Class Packet
    2. Property Time As Date
    3. Property Data As String
    4. Property Index As Int32
    5. End Class


    rgomez schrieb:

    Letzte Frage: Kann man Timers in .Net irgendwie miteinander synchronisieren, so dass sie exakt ticken???

    Nein, das ist nicht möglich. Grund: Handelsübliche Systeme sind nicht echtzeitfähig. Die Genauigkeit eines Threading-Timers beträgt etwa 50 ms, der Forms-Timer dürfte noch etwas schlechter sein.
    Gruß
    hal2000
    @EaranMaleasi Jou.
    Ein System.Threading.Timer wäre äquivalent.
    @rgomez Wie es aussieht brauchst Du gar keine For-Schleife, denn die ist nach der gewählten Anzehl von Umläufen beendet.
    Du lässt den Timer so lange laufen, bis alles fertig ist und dann stoppst Du ihn.
    Falls Du GUI-Ausgaben benötigst (Anzahl der Ticks, ein Fortschrittskriterium), kannst Du diese per .BeginInvoke() in einem geeigneten Control anzeigen lassen.
    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!