Я новичок в 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'