問題の概要
以下のような環境・構成で運用しているシステムがあります。
他社アプリから自社アプリへの連携動作時に画面が止まってしまう現象が発生して困っています。
似たような経験のある方のアドバイスや、調査方法等、教えて頂けたら幸いです。
環境
Windows7 または 10,.NET Framework 4.7.1,Linux(RedHatLinux7.6)
構成の説明
自社アプリの機能を他社アプリから呼び出す仕組みがあり、下のような構成を取っています。
A・B・Dは同一のWindowsPC上で動作し、CはLinuxサーバ上で動作します。
構成
A)他社デスクトップアプリ(C#.NETのWindows.Formsアプリ)
B)自社ライブラリ(VB.NETのDLL)…Aに組込みC・Dとの連携を担う
C)自社サーバアプリ(PHP, Perl)
D)自社デスクトップアプリ(VB.NETのWindows.Formsアプリ)
連携方式
- 処理の流れはA→B→C→D
- A→B:DLL組込みでメソッド呼出,戻り値受取
- B→C:HTTPリクエスト(GET),レスポンス受取
- C→D:Socket送信,受信
発生している問題
AがBのメソッド呼び出し
→BがCに通信
→CがDに通信
→DがCからの通知を受けて画面を表示する
という処理において、Dの画面表示イベント(From.Showメソッド実行後、Form.Loadイベント発生)処理前の段階で処理が停止し、メソッド戻り値を待っているAも画面が止まります。
画面は停止したままではなく、B→CのHTTPリクエストに設定した60秒のタイムアウトが過ぎると、Dの画面表示イベントが再開します。
この問題は毎回発生する訳ではなく、PC一台あたり毎日数十回以上繰り返される操作のうちに、数回発生する日もあれば、発生しない日もあります。
一度発生すると、Aを起動しなおすまでは同じ操作で再現します。
その状態でC→Dの部分のみ連携させると問題なく画面が表示されます。
止まっている状態でAを強制終了するとDの画面表示は即座に再開します。
また逆に、止まっている状態でDを強制終了するとAは即座に操作可能な状態に戻ります。
通信元と通信先で、互いに掴みあってロックしているような状態に見えます。
なかなか原因が特定できず、困っています。
該当のソースコード
※細かい部分は省略しています
A)他社デスクトップアプリ
C#
1public AppLink.AppLink App = null; 2App = new AppLink.AppLink(); 3string strRes = ""; 4strRes = App.Call(No);
B)自社ライブラリ・・・C)自社サーバアプリとhttp通信
VB
1Public Function Call(ByVal No As String) As String 2 'HttpWebRequestの作成 3 Dim sUrl As String = Settings.URL 4 sUrl = sUrl & "?no=" & No 5 Try 6 Dim req As HttpWebRequest = DirectCast(WebRequest.Create(sUrl), HttpWebRequest) 7 'サーバーからの応答を受信するためのWebResponseを取得 8 Dim res As System.Net.WebResponse = req.GetResponse() 9 Dim resStream As System.IO.Stream = res.GetResponseStream() 10 Dim sr As New System.IO.StreamReader(resStream) 11 Dim s As String = sr.ReadToEnd() 12 ' 読み込んだjsonをデシリアライズ 13 m_response = JsonConvert.DeserializeObject(Of apiResponse)(s) 14 sr.Close() 15 If m_response.result = apiResult.aNG Then 16 'サーバ内エラー時は"False"を返す 17 Log.WriteLog("sverr") 18 Return "False" 19 Else 20 '成功時はIDを返す 21 Return m_response.hogeID 22 End If 23 Catch ex As Exception 24 'サーバ通信不可時は"False"を返す 25 Log.WriteLog("neterr") 26 Return "False" 27 End Try 28End Function
D)自社デスクトップアプリ・・・C)自社サーバアプリとsocket通信
VB
1AddHandler Me.socketServer.ReceivedData, AddressOf server_ReceivedData 2 3Private Sub server_ReceivedData(ByVal sender As Object, ByVal e As ReceivedDataEventArgs) 4 Dim requestMsg As SocketRequestMsg = New SocketRequestMsg() 5 StatusCode = Event_Call(requestMsg) 6 'ステータスコード返信 7 e.Client.Send(StatusCode) 8End Sub 9 10Private Function Event_Call(ByVal requestMsg As SocketRequestMsg) 11 '画面表示 12 Invoke(New showfrmDelegate(AddressOf showfrm)) 13 return "200" 14End Funcion 15 16Delegate Sub showfrmDelegate() 17Sub showfrm() 18 Dim myFrm as frmHoge = New frmHoge 19 myFrm.Show(Me, False) 20End Sub 21 22Public Class frmHoge 23 Public Overloads Sub show(ByVal frm As frmMain, ByVal initialLoad As Boolean) 24 Me.TopMost = True 25 Me.Show() 26 Me.Activate() 27 End Sub 28End Class
試したこと
- A)他社デスクトップアプリとB)自社ライブラリで.NET frameworkのコンパイルバージョンを合わせる(4.7.1)→効果なし
- B)自社ライブラリのタイムアウト設定値を60秒から30秒に変更する→固まる時間が30秒に短縮された
- B)自社ライブラリのタイムアウト時にexceptionのmessageをログ出力→「操作がタイムアウトしました」