none
? zu "Seltsamer Programmablauf" RRS feed

  • Frage

  • Hoi,

    ich habe Folgendes Problem:

    in meinem Code wird an einer Stelle:

    1. nach einem Klick auf ein Label eine Picturebox mit einem neuen Bild geladen
    2. ein Schaltbefehl an einen Port einer RS485-Einheit übertragen (HIGH)
    3. eine Pause von 5 sek. gemacht
    4. ein erneuter Schreibbefehl an denselben Port ausgegeben (LOW)
    5. nach dieser Pause wird obige Picturebox wieder mit dem ursprünglichen Bild geladen

    Schritt 1,2,4 und 5 funktionieren tadellos - sobald ich aber die Pause einfüge passiert Folgendes:
    1. -
    2. Ja
    3. JA
    4. JA
    5. kann man nicht sagen da (1.) ja nicht durchgeführt wird.

    OHNE Pause geht das auch nur dann so schnell dass man den Wechsel der Bilder in der Picturebox nicht sehen kann.

    Hier mal die "Pause":

    Public Sub waitoneSeconds5()
    Dim start5, finish5, totalTime5 As Double
    finish5 = start5 + 5
    Do While Microsoft.VisualBasic.DateAndTime.Timer < finish5
    Loop
    totalTime5 = Microsoft.VisualBasic.DateAndTime.Timer - start5
    End Sub

    Wie gesagt, der Hardware-Part funktioniert (was am wichtigsten ist) aber die Visualisierung am Bildschirm muss ja auch erfolgen.

    Hier der Codepart für das Schalten nach Klick auf das Label (hier Label9):

        ' Signal 1: HP2
        Private Sub Label9_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Label9.Click
            StatusL1 = True
            PictureBox2.Image = ImageList1.Images(1)
            LabelS1G.Visible = True
            LabelS1R.Visible = False
            '  AxmeMPIO1.SetLine(2, 8)
            '    StatusL1 = True
            ' PictureBox2.Image = ImageList1.Images(2)
            ' Schalten
            Port33 = 1
    
            Dim Serialport1 As New SerialPort("COM4", 9600, Parity.None, 8, StopBits.One)
            If Serialport1.IsOpen = False Then
                Serialport1.Open() 'opens the serial port
                Dim data(3) As Byte
                data(0) = 255 'data for entering comand mode
                data(1) = 33 'data to select which relay 1-8, in this case 2
                data(2) = 1 'turn on the relay, or 0 to turn it off
                Serialport1.Write(data, 0, 3) 'write the data to the serial port,
                Serialport1.Close()
            End If
    
    
            ' Hier kommt die Pause
            waitoneSeconds5()
    
    
            StatusL1 = False
            LabelS1G.Visible = False
            LabelS1R.Visible = True
            PictureBox2.Image = ImageList1.Images(0)
            Port33 = 0
    
            If Serialport1.IsOpen = False Then
                Serialport1.Open() 'opens the serial port
                Dim data(3) As Byte
                data(0) = 255 'data for entering comand mode
                data(1) = 33 'data to select which relay 1-8, in this case 2
                data(2) = 0 'turn on the relay, or 0 to turn it off
                Serialport1.Write(data, 0, 3) 'write the data to the serial port,
                Serialport1.Close()
            End If
        End Sub

    Wäre nett, wenn mir jemand zumindest erklären könnte WARUM das so ist...eigentlich sollte das Programm ja Step by Step ausgeführt werden: warum es aber den Befehl zum Wechseln des Bildes in der Picturebox2 nicht durchführt sondern diesen Schritt überspringt und sofort die Pause ausführt ist und bleibt mir vollkommen schleierhaft.

    Gruß


    Be a good forum member - mark posts that contain the answers to your questions or those that are helpful

    Montag, 5. August 2013 09:22

Antworten

  • Hi,
    für die Aktualisierung der Oberfläche wird CPU-Zeit benötigt. Da Du aber mit der Do-Loop Schleife die CPU zu 100% beschäftigst, kann die Oberfläche nicht aktualisiert werden.

    Dieses Problem kann man lösen, indem man den Haupt-thread in den Wartezustand versetzt und erst nach Ablauf der Zeit wieder arbeiten lässt. So etwas kann man mit multi-threading organisieren. Am einfachsten geht das mit den neuen Möglichkeiten im Framework 4.5: async - wait.

    Alternativ kann man auch den BackgroundWorker oder einen Timer nutzen. Im Hauptthread wird der Timer gestartet und dann wird mit Wait gewartet. Der Timer-Tick sendet ein Signal, um dem Wait mitzuteilen, dass es weiter gehen kann. Schau Dir dazu mal den SyncronizationContext an.

    --
    Peter

    • Als Antwort vorgeschlagen Peter Fleischer Montag, 5. August 2013 11:46
    • Als Antwort markiert Ionut Duma Montag, 12. August 2013 06:34
    Montag, 5. August 2013 11:45

Alle Antworten

  • Hi,
    für die Aktualisierung der Oberfläche wird CPU-Zeit benötigt. Da Du aber mit der Do-Loop Schleife die CPU zu 100% beschäftigst, kann die Oberfläche nicht aktualisiert werden.

    Dieses Problem kann man lösen, indem man den Haupt-thread in den Wartezustand versetzt und erst nach Ablauf der Zeit wieder arbeiten lässt. So etwas kann man mit multi-threading organisieren. Am einfachsten geht das mit den neuen Möglichkeiten im Framework 4.5: async - wait.

    Alternativ kann man auch den BackgroundWorker oder einen Timer nutzen. Im Hauptthread wird der Timer gestartet und dann wird mit Wait gewartet. Der Timer-Tick sendet ein Signal, um dem Wait mitzuteilen, dass es weiter gehen kann. Schau Dir dazu mal den SyncronizationContext an.

    --
    Peter

    • Als Antwort vorgeschlagen Peter Fleischer Montag, 5. August 2013 11:46
    • Als Antwort markiert Ionut Duma Montag, 12. August 2013 06:34
    Montag, 5. August 2013 11:45
  • Hoi Peter,

    Danke für Deine Antwort.

    Also mit einem ganz normalen Timer aus der ToolBox ?

    OK, werde das mal ausprobieren....verstehe aber dennoch nicht, warum der Befehl zum Bildwechsel nicht ausgeführt wird - kommt ja VOR der Pause.

    Kann man nicht irgendwie warten bzw. abfragen bis die Picturebox das neue Bild geladen hat ?


    Be a good forum member - mark posts that contain the answers to your questions or those that are helpful


    • Bearbeitet Trixi-N Montag, 5. August 2013 12:11
    Montag, 5. August 2013 12:01
  • Hi,
    alles, was im Programm gemacht wird, macht die CPU. Das betrifft auch das "Malen" in der Oberfläche. Wenn Du die CPU zu 100% auslastest, bleibt keine Zeit zum "Malen". Du musst Dein Programm ins "Warten" bringen, damit sich die CPU mit anderen Dingen, wie beispielsweise dem "Malen", beschäftigen kann.

    Lösungswege dafür gibt es viele. Wichtig ist lediglich, dass Dein Programm pausiert, damit sich das System mit anhängigen Aufgaben, wie beispielsweise die Aktualisierung der Oberfläche, beschäftigen kann.

    Den Timer aus dem Werkzeugkasten hast Du nur, wenn Du auch eine Windows Oberfläche hast. Wenn Du Deine Funktionalitäten in einer Klasse in einer Klassenbibliothek gekapselt hast, gibt es andere Timer (threading timer, System timer).

    Da Du vermutlich Anfänger bist, kann man erst einmal auch ein DoEvents nutzen. Das bewirkt, dass Dein Programmablauf kurz unterbrochen wird und das System aufgefordert wird, alle anderen anhängigen Aufgaben, wie beispielsweise das Aktualisieren der Oberfläche, auszuführen.

    --
    Peter

    Montag, 5. August 2013 12:54
  • Hallo Trixi-N,

    Ich gehe davon aus, dass die Antwort Dir weitergeholfen hat.
    Wenn nicht, neue Rückfragen oder Ergänzungen zu diesem Thread bleiben weiterhin möglich.

    Danke und viele Grüße,
    Ionut


    Ionut Duma, MICROSOFT   Bitte haben Sie Verständnis dafür, dass im Rahmen dieses Forums, welches auf dem Community-PrinzipEntwickler helfen Entwickler“ beruht, kein technischer Support geleistet werden kann oder sonst welche garantierten Maßnahmen seitens Microsoft zugesichert werden können.

    Montag, 12. August 2013 06:33