Hallo,
ich verstehe grade nicht ganz, warum du ein Delay einbauen musst, um die Daten richtig zu empfangen (DoEvents sollte man sowieso immer vermeiden). Wenn der Head immer aus 7 Bytes besteht und ihm die Länge der restlichen Daten enthalten ist, weißt du ja nach dem Lesen des Heads, wieviele Daten noch kommen werden.
Wäre es hier nicht einfacher, z.B. einen neuen Thread zu starten, der in einer Schleife immer Daten empfängt (also Blocking I/O), anstatt ein Event zu verwenden? Dann könntest du z.B. eine Schleife machen, die immer zuerst den Head einliest, und danach den Rest, und hinterher den GUI-Thread benachrichtigt.
Also z.B. sowas wie
Private Sub verbinden_Click(ByVal sender As System.Object, ByVal e As _
System.EventArgs) Handles verbinden.Click
With SerialPort1
If Not .IsOpen Then
Try
.PortName = ComboBox1.Text
.BaudRate = 38400
.DataBits = 8
.Parity = Parity.None
.StopBits = StopBits.One
.WriteTimeout = 1000 ' 1000 ms = 1 Sek.
'.ReadTimeout = 1000 ' 1000 ms = 1 Sek.
.Open()
verbinden.BackColor = Color.Green
verbinden.Text = "Verbunden"
Dim readThread As New Thread( 'Lesethread
Sub()
ReadSerialPort(SerialPort1)
End Sub)
readThread.Start()
Catch ex As Exception
MessageBox.Show(ex.Message, "Fehler beim Open", _
MessageBoxButtons.OK, MessageBoxIcon.Error)
Exit Sub
End Try
End If
End With
End Sub
'Wird im Lesethread aufgerufen
Private Sub ReadSerialPort(port As SerialPort)
' Lesen
While True
' 7 Bytes Head lesen
Dim head As Byte() = New Byte(6) {}
Dim headBytesRead As Integer = 0
While headBytesRead < head.Length
Dim read As Integer = port.Read(head, headBytesRead, head _
.Length - headBytesRead)
headBytesRead += read
End While
'jetzt aus Head die Größe der restlichen Daten auslesen
Dim restlicheGroesse As Integer = .....
Dim body As Byte() = New Byte(restlicheGroesse - 1) {}
Dim bodyBytesRead As Integer = 0
While bodyBytesRead < restlicheGroesse
Dim read As Integer = port.Read(body, bodyBytesRead , _
restlicheGroesse - bodyBytesRead )
bodyBytesRead += read
End While
'GUI-Thread benachrichtigen, dass Telegramm empfangen wurde
BeginInvoke(New Action(Of Byte(), Byte())(AddressOf _
TelegramEmpfangen), head, body)
End While
End Sub
'Wird im GUI-Thread aufgerufen, wenn Telegramm empfangen wurde
Private Sub TelegramEmpfangen(head As Byte(), body As Byte())
'Weiterverarbeiten..
End Sub Die Read()-Methode kann allerdings eine TimeoutException werfen, weshalb ich das Setzen der Timeout-Eigenschaft oben auskommentiert habe (standardmäßig wird ein unendliches Timeout verwendet).
Beitrag wurde zuletzt am 21.02.12 um 20:18:27 editiert. |