2016-08-12 74 views
1

我有一个具有恒定输出到串行端口的权重比例。我做了一个应用程序,每3秒循环读一次秤上最新的重量,循环使用Async Sub,然后Await Task.Run(Sub()然后休眠3秒钟。我有两个问题。COMport.Readline()问题:洪泛缓冲区和字符串操作

首先,缓冲区充斥着数据,因此如果你减掉重量,比如说100磅,它仍然读取缓冲区中的旧数据,同时秤上的实际重量为0.但是它每3秒缓慢下降秒。我试图在Backgroundworker中连续循环readline(),但该比例仍然输出为快。我应该在readline()之前尝试'DiscardBuffer()'吗?还是有另一种阅读方法?

代码:COM端口道具

With COMScale 'COM Port Properties 

     .PortName = cmbPorts.Text 'COM Port Name 

     .Parity = IO.Ports.Parity.None 

     .DataBits = 8 

     .StopBits = IO.Ports.StopBits.One 

     .BaudRate = 9600 

     .ReceivedBytesThreshold = 1 

     .NewLine = vbCr 

     .ReadTimeout = 5000 

    End With 

代码:BackgroundWorker的

Private Sub BackgroundWorker1_DoWork(sender As Object, e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork 

    WeightA = 0 

    COMScale.DiscardInBuffer() 

    Try 

     COMScale.ReadTimeout = 10000 

     Do 

      Dim Incoming As String = COMScale.ReadLine() 

      If Incoming Is Nothing Then 

       Exit Do 

      Else 

       WeightA &= Incoming 

      End If 

     Loop 

    Catch ex As TimeoutException 

     WeightA = "N/A" 

     MsgBox(COMScale.PortName & "Timed Out") 

    Finally 

     'If com1 IsNot Nothing Then com1.Close() 

     lblWeightA.Text = WeightA 

    End Try 

End Sub 

第二个问题是规模输出,它喜欢这样的字符串...

“5?” & CHRW(2)& CHRW(2)& “?? J” & CHRW(2)& “; 47” & CHRW(2)& CHRW(2)& CHRW(2)& CHRW(2)&“?? J” & CHRW(2)& “; 475” & CHRW(2)& CHRW(2)& CHRW(2)& “?? J” & CHRW(2)& “; 475 00”

在规模说47.5磅

所有我需要的是最后的“475”数字,但有一个小数,所以字符串是47.5。我唯一能想到的是Right(string)问题,我使用Right(String)看到的问题是它可能是1000磅,100磅或10磅,所以它会切断我所需要的。这是我最好的选择吗?

+0

读数是否在每次读取后都有回车符或换行?你需要建立一个字符串,直到你得到整个消息然后使用它。 datarecieved事件随机发生,有时你只会得到整个字符串的一部分。您需要键入一个字符以知道流何时完成,然后使用它。我通常使用回调函数或[委托](https://msdn.microsoft.com/en-us/library/ms172879.aspx)。大多数情况下,意味着流的结束,然后我键入,然后触发我的委托函数来处理响应。 – Baddack

+0

对于第二部分,在char';'上做一个字符串'Split'。它会将字符串拆分为每个分号的字符串数组,然后您可以解析47500的最后一条记录。阅读规模手册,但您应该能够解析该值并除以1000. – Baddack

+0

我是使用'newline = vbCr'就是你的意思?我新使用串行端口。如果我不使用它,则不显示数据。 – holi4683

回答

0

而不是睡3秒你的应用程序应该连续阅读。然后缓冲区不会填满。

所以你的BackgroundWorker只是在一个循环中运行。也不要修改你的后台工作人员的任何UI元素。而是使用ReportProgress将其发送到表单。

Private Sub BackgroundWorker1_DoWork(sender As Object, e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork 
    COMScale.DiscardInBuffer() 
    Dim buffer As String 
    While e.Cancel = False 

     Try 

      buffer &= COMScale.ReadLine() 

      buffer = ProcessBuffer(buffer) 

     Catch ex As TimeoutException 
      BackgroundWorker1.ReportProgress(0, ex) 
     End Try 

    End While 
End Sub 

Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged 
    If TypeOf e.UserState Is TimeoutException Then 
     lblWeightA.Text = "N/A" 
     MessageBox.Show("Timeout") 
    ElseIf TypeOf e.UserState Is Decimal Then 
     lblWeightA.Text = CDec(e.UserState).ToString() 
    End If 
End Sub 

Private Function ProcessBuffer(inputBuffer As String) 
    'Parse your string. Looking for the last occurrence of the data you need. 

    If extractedPortion IsNot Nothing 
     BackgroundWorker1.ReportProgress(0, Decimal.Parse(extractedPortion)) 
    End If 

    Return leftOverChacters 
End Function 
+0

当我开始工作时,我会尝试这个星期一。 – holi4683

+0

哦,我等待3秒的原因是因为我需要在体重变化后让体重平衡,因为逻辑问题我不再使用它。 – holi4683

+0

我知道它在你的代码和msdn之间工作。我从一个例子中使用“我。 BackgroundWorker1.RunWorkerAsync(2000)'开始后台线程。你知道2000年的含义吗? – holi4683