我是异步,等待,任务等的新手。
我正在将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'