パイプを使用して、レガシーアプリケーション(COBOLで記述)を.NETの新しいアプリケーションに接続しています。考え方は単純です。レガシープログラム(私のERPメニュー)はストリームにいくつかのパラメーターを書き込み、.NETアプリはストリームを介してそれを読み取り、Console.In
要求された画面を開く新しいスレッドを開始します。アイデアがどのように機能するかについての.NET側の抜粋を次に示します。
<STAThread(), LoaderOptimization(LoaderOptimization.MultiDomain)>
Shared Sub Main()
If Environment.GetCommandLineArgs(1) = "PIPE"
While True
Dim pipeParam as String
Try
pipeParam = Console.In.ReadLine()
Catch e as Exception
Exit Sub
End Try
' Deal with parameters here
If pipeParam = "END"
Dim newThread as New Threading.Thread(Sub()
' Create a new AppDomain and Loads the menu option, generally a Winforms form.
End Sub)
newThread.Start()
End If
End While
End If
End Sub
すべてがうまく機能し、簡単でした...今日まで。このソリューションをクライアント環境(Windows Server 2003)に展開しましたが、呼び出されたプロセス(COBOL)が終了している(つまり、Console.In
強制的に閉じられている)場合を除いて、要求されたスレッドが実行されていませんでした。それ以降、要求されたすべてのWinFormが表示され、期待どおりに動作し始めます。
この奇妙な振る舞いをログで掘り下げると、IDictionary.ContainsKey()
ステートメントが実行されるポイント(またはネイティブコードの実行を必要とする他のメソッド)までスレッドが正常に実行されていることがわかりました。この時点で、スレッドはフリーズ/スリープ状態でした。
スレッドの作成をたとえば3つに制限すると、作成されたすべてのスレッドが3番目のスレッド、つまりConsole.In.ReadLine
実行されなくなるまでハングすることがあります。
何を試してみればいいですか?何かアドバイスはありますか?
さらに詳しい情報:これまでに見つけた最も近い方向は、この質問に対するHans Passantの回答でした: マルチスレッドc#アプリケーションでインターフェイスがフリーズします(.NET SystemEventsがdebbugerスレッドリストに表示されますが、解決できませんでした提案された解決策に関する私の問題)。
更新されたニュース
サブスレッドがのロードを完了するのを待つことで、この問題を解決できますForm
。この「IsReady」信号はとを通過しAppDomain.SetData()
ますAppDomain.GetData()
。どういうわけか、フォームの作成後、メインスレッドが続行してもサブスレッドはフリーズしなくなりましたConsole.ReadLine
。問題は解決しましたが、私はこれに興味を持っています。私はこれを「可能な限り単純な」テストケースで再現しようとしています。
いくつかの詳細
- エントリポイントの.exeは32ビットにコンパイルされます。他のすべてのライブラリは「AnyCpu」です。この問題は、32ビット(クライアント)と64ビット(開発)の両方のマシン(Windows Server 2003の両方)で実行されている場合に発生します。
Sub Main()
上記のスニペットの属性を更新しました。Console.ReadLine
をワーカースレッドに入れようとしました。解決しませんでした(下の画像を参照)。- COBOLアプリケーションは、別のOSプロセスで実行されるため、フリーズしません。パイプはたまたま私のIPCアプローチです。この場合のCOBOLアプリケーションは、パラメーターを書き込むだけで、応答を待ちません。
- スタックトレースは下の画像にあります(
PRX001235
データベースに接続する前、およびフォームを効果的にロードする前に、スレッドはxml構成ファイルを逆シリアル化しています-この場合、まだマネージコードにあるようです-PRX001235
スレッドがネイティブコードでフリーズすることがありますデータベースに接続しようとしています):