2012-01-19 100 views
4

我有一個使用.NET SerialPort類的C#應用​​程序。我用來從串口獲取數據的代碼並不特別。關鍵的部分是C#和SerialPort類截斷數據

//Open the port 
      comport.BaudRate = myPort.BaudRate; 
      comport.StopBits = StopBits.One; 
      comport.DataBits = 8; 
      comport.Parity = Parity.None; 
      comport.ReadTimeout = 20000; 


      comport.PortName = myPort.PortSystemName; 
      comport.Handshake = Handshake.None; 
      comport.RtsEnable = true; 


      comport.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived); 
comport.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived); 

    private void port_DataReceived(object sender, SerialDataReceivedEventArgs e) 
     { 

      string msg = ""; 
      try 
      { 
       msg = comport.ReadExisting(); 

       if (comport.IsOpen) 
        comport.Close(); 
     } 

此代碼工作完全正常在Windows XP。但是,在Windows 7上,無論發送什麼數據,都會遇到問題,它只會提取前四個字符。所以在諸如「123456」的字符串中,味精將是「1234」。收集數據的設備是RFIdeas pcProx,我已驗證數據是否正常。我也證實了超級終端中的數據看起來不錯。因此,我在代碼中採集數據的方式肯定有些奇怪。幫幫我!

+0

附註:我發現即使代碼相同,在串行/控制或手動創建時,「SerialPort」的行爲也會有所不同。 – leppie

回答

5

這完全符合API。它不是,也從未保證讀取所有內容:

此方法以字符串的形式返回串行端口對象的流和內部緩衝區的內容。此方法不使用超時。請注意,此方法可能會在內部緩衝區中留下尾部前導字節,這會使BytesToRead值大於零。

此外,你需要處理「還沒有在內部緩衝區」 - 你不只是閱讀而BytesToRead是積極的。這通常涉及循環和緩衝,直到收到完整的消息。

您的工作是通過使用諸如行尾等標記或使用長度前綴頭來讀取適量的數據。

如果它在XP上運行的很好,那麼這只是一筆好運(也許是由於某些時間和/或效率的調整)。

上面的一切同樣適用於大多數輸入,而不僅僅是串口;例如,文件IO和網絡IO的工作原理幾乎完全相同。

+0

所以你會建議像循環檢查bytestoread爲零?或者從代碼的角度來看,你會提出什麼建議? –

+0

@Jim我明白**不會**太多BytesToRead,因爲它只是告訴你什麼是可用的 - 它沒有說沒有更多的數據來。如果可能的話,我會使用ReadLine(),並使用新行來分隔數據。如果你不能使用ReadLine(),那麼是的:你需要循環。但是:知道您何時擁有所有數據是由您的協議定義的。沒有一些定義(例如,長度前綴或換行符終止),不可能區分「1234」和「12345」,但5仍然是傳入並且尚未到達,因此只有1234可用「 –

+0

OK,很公平。我想我可以將我的設備設置爲發送比任何可能的數據都長的固定長度的字符串,以便我可以鍵入字符串的長度。 –