質問: いつもお世話になっております。 今回の質問はデータを連続で送信している際にメインフォームが操作できなく現象についてです。 現象の再現方法 1,TCP_TEST_FORM_APPRI_SERVERのメインフォームからServerFormを二つ以上立ち上げる。 2.TCP_TEST_FORM_APPRI_CLIENTを立ち上げて二つ以上接続する。 3,TCP_TEST_FORM_APPRI_SERVER側で設定画面から連続送信チェックボタンにチェックをする。 4,TCP_TEST_FORM_APPRI_CLIENT側で何らかの文字をサーバーに送る。 5,TCP_TEST_FORM_APPRI_SERVERのメインフォームが操作できず、サーバー側からデータが送られ続ける状態となる。 やりたい事はある特定の文字がきたらサーバー側が文字を連続で返すようにしたく、連続送信をサーバー側で止める事のできる形にしたいのです。 連続送信時はクライアント側からデータが受け取れる状態にもしたいと考えています。(クライアント側からも停止文字を送りたい為。) フォームの操作ができなくなるとは考えいなかったので、困っています。 これはスレッドの重複によるものなのか、それともループのしすぎでほかの処理ができなくなっているのか、どなたかわかる方がいらっしゃればご教授をお願いします。 前回と同様にProjectをアップロード致しますので、お手数をかけますがDLしてソースを見てもらえればと思います。 リンク内容:DLパス 今年の西暦4桁を数字で ``` Private Sub ContinuousSendMethod(ByVal sendData As String) Try Do If setting.NoContinueCheck.Checked Then Exit Do End If '送信文字一覧に書き込む RaiseEvent WriteSendData(sendData) '送られてきたデータの判定をクライアント側に送信 SendCode(sendData) Loop Catch ex As Exception RaiseEvent WriteLog("連続送信時エラー " + ex.ToString()) Return End Try End Sub ```
回答: 連続送信のループに処理が取られ過ぎて、他の処理が動けていないみたいです。 下記のようにループ内にウエイトを入れて、他の処理を実行する余裕を作りましょう。 ``` Private Sub ContinuousSendMethod(ByVal sendData As String) Try Do If setting.NoContinueCheck.Checked Then Exit Do End If '送信文字一覧に書き込む RaiseEvent WriteSendData(sendData) '送られてきたデータの判定をクライアント側に送信(このメソッド内で呼ばれた場合は受信データは常に同じ 別スレッドで判定され、測定終了となる。) SendCode(sendData) 'CPUを逃がす Threading.Thread.Sleep(0) Loop Catch ex As Exception RaiseEvent WriteLog("連続送信時エラー " + ex.ToString()) Return End Try End Sub ``` 現状ですと、クライアントからデータが送信されるたびに、連続送信用のスレッドが開始されます。 この為、クライアント側の受信処理でも負荷が上がり操作が利きにくくなっていきます。 ですので、ここら辺も考慮したプロトコルを設計する必要があると思います。 また、以前指摘したようにTCPクラスからフォームのコントロールをアクセスすべきではありません。 (今回はsetting.NoContinueCheck.Checked) 今後、クライアントからの送信データでも連続送信を停止したいとのことですから、 連続送信を行うかどうかのプロパティを用意し、連続送信処理でそのプロパティを見るとしたほうが良いと思います。 ``` ''' ''' 連続送信を行うかどうかを設定、取得する。 ''' ''' False:連続送信しない True:連続送信する Public Property ContinuousSend As Boolean ' ' 受信処理内 ' '受信文字一覧に書き込み依頼 RaiseEvent WriteRecivedData(resMsg) If resMsg = "連続送信停止" Then ContinuousSend = False End If If ContinuousSend Then '連続送信用スレッド Dim continuousSend As Thread = New Thread(New ParameterizedThreadStart(AddressOf ContinuousSendMethod)) continuousSend.Start(resMsg) Else '送られてきたデータを判定し、送信データの作成及びデータの送信処理 SendCode(resMsg) End If RaiseEvent WriteSendData(resMsg) ''' ''' 連続送信用メソッド ''' ''' 送信データ ''' メインスレッド、通信スレッドでもなく、3つ目のスレッド Private Sub ContinuousSendMethod(ByVal sendData As String) Try While ContinuousSend '送信文字一覧に書き込む RaiseEvent WriteSendData(sendData) '送られてきたデータの判定をクライアント側に送信(このメソッド内で呼ばれた場合は受信データは常に同じ 別スレッドで判定され、測定終了となる。) SendCode(sendData) Threading.Thread.Sleep(0) End While Catch ex As Exception RaiseEvent WriteLog("連続送信時エラー " + ex.ToString()) Return End Try End Sub ```