VB.NET - Проблема чтения последовательного порта - состояние «Ожидание активации» - PullRequest
0 голосов
/ 14 февраля 2019

Я новичок в Async, Await, Task и т. Д.

Я посылаю командную строку Ascii в последовательный порт, а затем считываю 9 байтов, возвращенных как измеренное значение из порта.

Если команда (команда измерения напряжения) отправлена ​​и получена прибором, она возвращает 9 байтов.Это нормальный случай.Это прекрасно работает, если есть 9 байтов для чтения.

Однако, если ничего не возвращается, потому что командная строка не передала должным образом (скорее всего), а затем прибор ничего не возвращает, то вместо ожидаемых 9 байтов ничего не читается, а Read.status равен «Ожидание»для активации "

Теперь, если я снова отправлю команду после неудачного события чтения, то измеренное значение не будет считано должным образом.Я получаю 5 байтов вместо ожидаемых 9 байтов или иногда ничего не читается

Я читаю порт, используя

Dim read = Port.BaseStream.ReadAsync(readback, readback.Length - bytesLeft, bytesLeft)

Несколько попыток чтения не решают проблемупроблемаКажется Port.BaseStream.ReadAsync() фиксируется в определенном состоянии, если требуемое количество байтов не читается, и это сохраняется до тех пор, пока оно не будет сброшено каким-либо образом..Я не знаю как его сбросить.

Как я могу сбросить состояние Port.BaseStream.ReadAsync() после неудачного события чтения, чтобы, если я попытаюсь снова отправить команду и снова прочитать порт, она будет работать нормально?

Вот код функции GetLoadVoltage, который отправляет команду и затем вызывает функцию ReadAllBytes для считывания измеренного значения с последовательного порта.

Любая помощь или совет приветствуется!

Async Function GetLoadVoltage(address As UInt16, channel As UInt16, cancelToken As Threading.CancellationToken) As Task(Of Double) Implements ILoadComms.GetLoadVoltage

Try
            'Variables and Set-Up
            Dim trys = 0

            Dim command1 As Byte() =
               System.Text.Encoding.ASCII.GetBytes("@" + 
               address.ToString("00") + "L" + channel.ToString("0") + "V?")


            Await TimeLimitedWrite(command1)

            Dim readback1 = Await ReadAllBytes(9, cancelToken)


            cancelToken.ThrowIfCancellationRequested()

            Dim adrs As String = address.ToString("00")
            Dim pattern As String = adrs + ":\d{3}\.\d{1}"
            Dim input As String = 
            Text.Encoding.ASCII.GetString(readback1).Replace(vbCr, "")

            Dim m As Match = Regex.Match(input, pattern, 
            RegexOptions.IgnoreCase)

            If m.Success Then
                Return CDbl(System.Text.Encoding.ASCII.GetString(readback1, 
                3, 5))
            Else
                While m.Success = False
                    If trys < 5 Then
                        StarPrint("Corrupted string " + input, _logs)
                        StarPrint("GetLoadVoltage Retry " + trys.ToString, 
                        _logs)
                        trys = trys + 1
                        command1 =
                        System.Text.Encoding.ASCII.GetBytes("@" + 
                        address.ToString("00") +"L" + channel.ToString("0") 
                        + "V?")
                        Await TimeLimitedWrite(command1)
                        readback1 = Await ReadAllBytes(9, cancelToken)
                        input = 
                      Text.Encoding.ASCII.GetString(readback1).Replace(vbCr, 
                       "")
                        m = Regex.Match(input, pattern, 
                        RegexOptions.IgnoreCase)
                    Else
                        Throw New CommsInvalidException("GetLoadVotage(): 
                        Format exception 1")
                    End If
                End While
                Return CDbl(System.Text.Encoding.ASCII.GetString(readback1, 
               3, 5))
            End If
        Catch cancelEx As OperationCanceledException
            Throw
        Catch ex As Exception
            Throw
        End Try
    End Function '

*************** Это функция чтения ************

Protected Async Function ReadAllBytes(expectedBytes As Integer, cancelToken As Threading.CancellationToken) As Task(Of Byte())

Try
            Dim trys = 0
            Dim readback(expectedBytes - 1) As Byte
            Dim bytesLeft = expectedBytes

            readWatch.Reset()
            readWatch.Start()

            While bytesLeft <> 0
                Dim read = Port.BaseStream.ReadAsync(readback, readback.Length - bytesLeft, bytesLeft)
                Await Task.WhenAny(Task.Delay(5000), read)

                While read.IsCompleted = False
                    If trys < 5 Then
                        _logs.PrintToDebug("Read all bytes RETRY : " + trys.ToString)
                        trys = trys + 1
                        read = Port.BaseStream.ReadAsync(readback, readback.Length - bytesLeft, bytesLeft)
                        Await Task.WhenAny(Task.Delay(3000), read)

                    Else

                        ' If (Flagged.Contains(Port.PortName)) Then
                        'Flagged.Remove(Port.PortName)
                        'End If
                        'Return readback

                        Throw New CommsReadTimeoutException("ReadAsync Timed Out trying to read " +                 expectedBytes.ToString() + " Bytes")
                    End If
                End While

                bytesLeft = bytesLeft - read.Result
            End While

            If (Flagged.Contains(Port.PortName)) Then
                Flagged.Remove(Port.PortName)
            End If

            readWatch.Stop()
            Dim format As String = "{0,-10} {1,-5} {2, -10} {3, -10}"
            Dim rdBk As String = Text.Encoding.ASCII.GetString(readback).Replace(vbCr, "")
            Dim Milli As String = "Ms: " + readWatch.ElapsedMilliseconds.ToString ' Ms for milliseconds
            Dim PrtNme As String = Port.PortName
            Dim rd As String = "READ"
            _logs.PrintToDebug(String.Format(format, Milli, PrtNme, rd, rdBk))

            cancelToken.ThrowIfCancellationRequested()
            Return readback
        Catch ex As InvalidOperationException
            _logs.PrintToDebug("ReadAsync Eror trying to read")
            Throw New InvalidOperationException("ReadAsync Error: " + ex.Message, ex)
        Catch ex As CommsReadTimeoutException
            _logs.PrintToDebug(ex.Message)


            Throw
        End Try
    End Function'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...