2012-03-21 8 views
2

一部のUSBシリアルポートアダプタが.NETでうまく動作しない理由を診断しようとしています。影響を受けるアダプターの動作は、SerialPort.Write()の後です。 のいずれかを呼び出すと、SerialPort.Readxxx()メソッドが約ReadTimoutまでブロックされます。 私が発見した回避策は、ループをブロックしてBytesToRead<= 0である間にブロックし、すべて正常に動作することです。どうして?.NETでのSerialPortクラスの問題

Sysinternals 'Portmonを使用してsome debug logsを収集しました。なぜこうなった?

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

私はReadByte()の2つのネイティブ実装を書いており、問題の特性をより明確にすることができます。 ReadIntervalTimeoutとReadTotalTimeoutMultiplierをMAXDWORD ReadFile()に設定すると、 は、受信バッファにバイトが入るのを待ってから、MSDNの COMMTIMEOUTS構造体ページに記載されているように返されます。

これは、ReadByte()がシリアルポートを設定する方法であることを示しています。しかし、 ReadFile()がReadFile()と呼ばれるときに受信バッファが空の場合、ReadTotalTimeoutConstantまで待機してから復帰します。 Microsoftの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%がアプリに到達することはありません –

+1

"DataReceivedEventが発射することが保証されていない"理由を説明できますか? –

+0

DataReceivedイベントは、受信されたバイトごとに発生するとは限りません。 BytesToReadプロパティを使用して、バッファに読み込まれるデータの量を判断します。http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.datareceived.aspx –