タイトル : Re^2: シリアル通信で異常に時間がかかってしまう 投稿日 : 2010/01/26(Tue) 17:36 投稿者 : ぽると
GODさん アドバイスありがとうございます。 > とりあえずDoEventsは使用しない方が良いですよ。 ご指摘のとおり、Unload 後に勝手にロードされる問題はありました。 強引ですが、全ての内部タイマーやオブジェクトを解放後に End で終了するようにしています。 > PC1側のプログラムにはコマンドのリトライ制限はないのですか?また、リトライ処理があるなら正しく動作していますか?(コマンド送出タイミングと回数) > PC2側がわざと応答を返さない時(全コマンドで実験?)は正しく動作してるかな? PC1とPC2の通信は TCP/IP による通信のみで、特にリトライ制限等は設けていません。 PC2側がなんらかの原因でPC1側に応答を返さない場合、PC1側で、異常と判断して知らせる形になっています。 システム構成について、もう少し全体の構成を説明しますと、 PC1を統括用として、そこから命令を受け取り、各装置に命令を送信するPCが複数あります。 PC1と各制御用PCは TCP/IP にて装置状態やコマンドをやりとりして、 制御用PCと装置は シリアル通信 にて通信しています。 (図) 統括用PC 装置用PC PC1 ⇔ PC2 ⇔ 装置2 ⇔ PCX ⇔ 装置X ⇔ PCY ⇔ 装置Y ⇔ PCZ ⇔ 装置Z ↑ ↑ TCP/IP通信 シリアル通信 追記になってしまい恐縮ですが、通信関係のイベントの一覧をまとめました。 通信部分のみを抜粋しています。 '// ◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆ '// PC1( TCP通信タイマー と TCPコントロール ) '// ◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆ '// -------------------------------------------------- '// TCP通信タイマー '// -------------------------------------------------- Private Sub timerTcp_Timer() ' .Interval は 100ms timerTcp.Enabled = False ' タイマー停止 With tcpControl ' TCP/IP 通信 .Timeout = 3000 ' 切断されている時は再接続処理 If (.State <> tcpConnected) And (.State <> tcpConnecting) Then Call .Connect( <PC2>, <通信ポート> ) End If Select Case .State Case tcpConnected ' 接続状態ならコマンド送信 Call .Send( <コマンド文字列> ) Case tcpClosed, tcpClosing Case tcpConnecting End Select End With timerTcp.Enabled = True ' タイマー再開 End Sub '// -------------------------------------------------- '// TCP コントロール処理 '// -------------------------------------------------- Private Sub tcpControl_State() <接続状態の表示を更新するだけなので省略> End Sub Private Sub tcpControl_Receive() With tcpControl .Timeout = 0 Call .Receive(mstrBuffer) ' mstrBuffer は Public 変数 ' 状態判定等の処理は別関数で処理 .Timeout = 3000 End With End Sub Private Sub tcpControl_Error(ByVal Number As DartSockCtl.ErrorConstants, ByVal Description As String) With tcpControl .Timeout = 0 If (.State <> tcpClosed) And (.State <> tcpClosing) Then Call .Close End If End With End Sub '// ◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆ '// PC2( シリアル通信タイマーと MsComm、Winsock ) '// ◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆ Private Sub timerComm_Timer() ' .Interval は 100ms <前述したシリアル通信処理> End Sub Private Sub winsockDaemon_ConnectionRequest(ByVal requestID As Long) With winsockClient If .State <> sckClosed Then .Close .LocalPort = 0 .Accept requestID End With End Sub Private Sub winsockClient_DataArrival(ByVal bytesTotal As Long) Dim lstrBuffer As String winsockClient.GetData lstrBuffer If (winsockDaemon.State <> sckListening) And (winsockDaemon.State <> sckClosed) Then winsockDaemon.Close End If winsockDaemon.Listen If (winsockClient.State <> sckConnected) And (winsockClient.State <> sckClosed) Then .Close End If End Sub Private Sub winsockDaemon_Error( <省略> ) If WinsockDaemon.State <> sckClosed Then .Close End Sub Private Sub winsockClient_Error( <省略> ) If winsockClient.State <> sckClosed Then .Close End Sub 以上のようなつくりになっています。 DoEvents 方式を排除してしまうのが一番だとは思うのですが、 装置毎に個別のPGがあり、Comm用クラスも個別にカスタマイズが入っているようで、 なんとか最小の変更で対応できないものかと苦心しています。 |