Краткое предисловие к тому, что я пытаюсь сделать. Я хочу запустить процесс и запустить два потока для мониторинга stderr и stdin. Каждый поток обрабатывает биты потока и затем запускает его в NetworkStream. Если есть ошибка в любом потоке, оба потока должны немедленно умереть.
Каждый из этих процессов с потоками мониторинга 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);
}
Этот блок кода выполняется в одном потоке, который сейчас не является фоновым. Есть похожая тема для потока StandardError. Я использую этот метод вместо того, чтобы слушать OutputDataReceived и ErrorDataReceived, потому что в Mono была проблема, из-за которой эти события не всегда срабатывали должным образом, и, несмотря на то, что теперь это кажется исправленным, мне нравится, что этот метод гарантирует, что я читаю и пишу все последовательно.
ShutdownClient с True просто пытается уничтожить оба потока. К сожалению, я нашел единственный способ сделать эту работу - использовать прерывание для объектов stdErrThread и stdOutThread. В идеале peek не должен блокироваться, и я мог бы просто использовать событие ручного сброса для проверки новых данных в stdOut или stdIn, а затем просто умереть, когда событие перевернуто.
Я сомневаюсь, что это лучший способ сделать это. Есть ли способ выполнить это без использования прерывания?
Я хотел бы изменить, потому что я только что увидел в своих журналах, что пропустил исключение ThreadInterruptException, выброшенное в Utlities.ConsoleOut. Это просто делает System.Console.Write, если статическая переменная истинна, но я предполагаю, что это где-то блокирует.
редактирует:
Эти потоки являются частью родительского потока, который массово запускается сервером по запросу. Поэтому я не могу установить потоки StdOut и StdErr на фон и убить приложение. Я мог бы убить родительский поток с главного сервера, но это опять-таки застряло бы с блокировкой Peek.
Добавлена информация о том, что это сервер.
Кроме того, я начинаю понимать, что лучшим методом решения для очереди может быть окончательное решение.