2016-08-12 33 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