RS232Cで通信しているのですが、送信時に1~30秒ほどの待ちが発生することがあり、
その解消に苦労したので記録します。
○ SerialPortクラスは使わずに、WindowsAPI WriteFile(), ReadFile()を使用している。
(ReadFileは別スレッドでループを回している)
○ 開発環境のハイスペックPCでは待ちが発生しない。
○ RS232Cポートを増設して、そちらで試しても待ちが発生する。
○ USB-RS232C変換ケーブルを使用しても待ちが発生する。
○ フリーのRS232Cテストツールを使用したところ、待ちは発生しない。
○ ケーブルや、通信相手を変更しても、待ちは発生する。
○シリアルポートの設定、BIOSの設定、レジストリの割り込み設定、
デバイスマネージャのIRQ設定を調整しても、待ちが発生する。
過去に作ったプログラムなのですが、
当時はSerialPortクラスでの読み取りに何らかのトリガーが必要だと思い込み、
試しもせずにWindowsAPIを使うという、イバラの道(初心者には)を選んだのでした。
その時は書き込み時の遅延はあまり問題にならなかったのですが、
今回通信部分を流用して別のプログラムを作成したところ、
今回の送信時の遅延が発覚しました。
ネットでダウンロードしたツールだと待ちが発生しないので、
明らかに私のプログラムに問題があります。
正常に動くツールはSerialPortクラスを使っているということで、
SerialPortクラスの使い方を眺めていると、
普通に受信時にイベントがはっせいするだけでしたので、
急遽、送信部分と受信部分をSerialPortクラスを使うように修正しました。
あっさりと送信時の遅延は解消ました。
色々試していくうちに、
読み取りのループを止めると書き込み時の遅延が発生しないことがわかりました。
ということは、送信と受信の競合が問題になりそうですね。
ということで、WriteFile() ReadFile() しているところに、
SyncLock _syncObj という感じで、排他制御を入れたところ、
送信時の待ちは解消されました。
RS232C通信の送信と受信は排他すること。(もしくはSerialPortクラスを使用する)
今度はTCP/IPの通信なのですが、送信と受信をSyncLock _syncObjしたところ、
スペックの低いPCだとなぜかデッドロックが起こる、
ということが以前にありました。
こちらはSocketクラスを使用しています。
昔のコードを掘り返して確認すると、
送信部の SyncLock _syncObj をやめることで、
デッドロックを解消していました。
AIとお話ししたところ、
送信部分のSocket.Send() と受信部分のCallBackがロックを取り合っていることが原因で、
TCP/IP 通信では Socket.Send() した後に、
受信の待ちが発生することがあるので、送信と受信でロックを取り合ってはダメとのことでした。
TCP/IP(Socket)通信では、送信と受信は排他しないこと。
※送信、受信が重複しないように、別のロックで、送信、受信を別々にロックした方が良い。
ということでした。