私がしようとしていることの簡単な前書き。私はプロセスを開始し、stderrとstdinを監視するために2つのスレッドを起動したい。各スレッドはストリームのビットを噛み砕き、それをNetworkStreamに送り出します。いずれかのスレッドにエラーがある場合は、両方のスレッドがただちに終了する必要があります。StreamReader.PeekとThread.Interruptの代わりに
stdoutおよびstdin監視スレッドを持つこれらの各プロセスは、メインサーバープロセスによって分離されます。これが難しくなる理由は、いつでもこれらのプロセスが40または50になりやすいからです。朝の再起動バーストの間だけ、50以上の接続がありますが、実際には100以上を処理できる必要があります。私は100の同時接続でテストします。
try
{
StreamReader reader = this.myProcess.StandardOutput;
char[] buffer = new char[4096];
byte[] data;
int read;
while (reader.Peek() > -1) // This can block before stream is streamed to
{
read = reader.Read(buffer, 0, 4096);
data = Server.ClientEncoding.GetBytes(buffer, 0, read);
this.clientStream.Write(data, 0, data.Length); //ClientStream is a NetworkStream
}
}
catch (Exception err)
{
Utilities.ConsoleOut(string.Format("StdOut err for client {0} -- {1}", this.clientID, err));
this.ShutdownClient(true);
}
このコードブロックは、現在の背景ではない1つのスレッドで実行されます。 StandardErrorストリームにも同様のスレッドがあります。私はOutputDataReceivedとErrorDataReceivedをリッスンする代わりにこのメソッドを使用しています。なぜなら、これらのイベントが常に正しく発生するとは限らないMonoに問題があったからです。このメソッドでは、順次。
Trueを指定したShutdownClientは、単に両方のスレッドを強制終了しようとします。残念ながら、私がこの作業を行うために見つけた唯一の方法は、stdErrThreadおよびstdOutThreadオブジェクトに対して割り込みを使用することです。理想的にはピークがブロックされず、手動リセットイベントを使用してstdOutまたはstdInの新しいデータをチェックし、イベントが反転されたときにただ死ぬことができます。
私はこれを行うのが最善の方法だとは思っていません。割り込みを使用せずにこれを実行する方法はありますか?
私は、私のログで、Utlities.ConsoleOutの内部にスローされたThreadInterruptExceptionが見つからなかったので、私は変更したいと思います。これは、静的変数がtrueの場合はSystem.Console.Writeを実行しますが、このブロックがどこかにあると思います。
編集:
これらのスレッドは、要求に応じて、サーバによって一斉に発売された親スレッドの一部です。したがって、StdOutおよびStdErrスレッドをバックグラウンドに設定してアプリケーションを強制終了することはできません。私はメインサーバーから親スレッドを削除することができますが、これはPeekブロックでもスティッキーになります。
これがサーバーであることに関する情報を追加しました。
また、私はクエリのためのより良いキューイング方法を実現し始めています究極のソリューションかもしれません。
他の人が簡単に見ることができますので、私は元の質問に編集としてこれを追加します。しかし、これは、2つのストリームスレッドを使用して、時には何百ものプロセスを生成するサーバーです。アプリケーション全体が死ぬことはありません。メインサーバーにこの子スレッドを強制終了するように指示することができましたが、Peekブロッキングのために再びスティッキーになります。 – Mark