2012-03-21 102 views
2

我在嘗試診斷爲什麼某些USB串行端口適配器不適用於.NET。受影響的適配器的行爲在SerialPort.Write()之後。調用 中的任何一個SerialPort.Readxxx()方法導致該方法阻塞,直到約ReadTimout。 我發現的解決方法是使用循環來阻止,而BytesToRead<= 0,然後一切按預期工作。爲什麼?.NET中SerialPort類的問題

我已收集some debug logs使用Sysinternals'Portmon。這是爲什麼發生?

without.log = bad behavior/bad USB adapter 
with.log = with the while loop/bad USB adapter 
ftdi.log = good behavior/good USB adapter 

我寫了ReadByte()的兩個本地實現,現在可以更好地表徵問題了。 使用ReadIntervalTimeout和ReadTotalTimeoutMultiplier設置爲MAXDWORD ReadFile(),它是 應該等到一個字節在接收緩衝區中並按照MSDN的 COMMTIMEOUTS結構頁面中所述返回。

Portmon日誌顯示這是ReadByte()設置串口的方式。但是,如果 在ReadFile()被調用ReadFile()時接收緩衝區爲空,它將一直等到ReadTotalTimeoutConstant並返回。 微軟的ReadByte()也設置了一個Comm事件; Portmon日誌清楚地顯示事件正在觸發,但ReadByte()從不讀取接收緩衝區。我在我的本地版本的ReadByte()中實現了它,並且它與受影響的USB轉串口適配器完美協作。

Native ReadByte()

回答

1

最好的辦法閱讀的SerialPort使用異步OU中方法:

_port = new SerialPort(); 
_port.DataReceived += new SerialDataReceivedEventHandler(OnComPortDataReceived); 

void OnComPortDataReceived(object sender, SerialDataReceivedEventArgs e) 
{ 
    byte[] ba = new byte[_port.BytesToRead]; 
    total = _port.Read(ba, 0, _port.BytesToRead); 
} 
+1

的DataReceivedEvent不能保證火了,在我的測試中的事件的40%永遠不會到達應用 – 2012-03-21 20:25:55

+1

你能解釋爲什麼「DataReceivedEvent不能保證觸發」? – 2012-03-21 20:27:05

+0

對於接收到的每個字節,都不能保證DataReceived事件發生。使用BytesToRead屬性來確定在緩衝區中有多少數據需要讀取http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.datareceived.aspx – 2012-03-21 20:50:43