Чтение вывода другой консоли процесса - PullRequest
6 голосов
/ 19 марта 2011

У меня проблема, когда вывод консоли возвращается в 'waves'. Например, консоль выводит что-то каждую секунду, и, например, событие запускается 60 раз каждую минуту (все события одновременно).

Мой код:

Process Proc = new Process();
Proc.StartInfo.FileName = SSMS.BinaryDir + "HldsUpdateTool.exe";
Proc.StartInfo.Arguments = "-command update -game tf -dir " + SSMS.RootDir + Key;
Proc.StartInfo.UseShellExecute = false;
Proc.StartInfo.RedirectStandardOutput = true;
Proc.StartInfo.RedirectStandardError = true;

Proc.EnableRaisingEvents = true;
Proc.StartInfo.CreateNoWindow = false;

Proc.ErrorDataReceived += new DataReceivedEventHandler(Proc_ErrorDataReceived);
Proc.OutputDataReceived += new DataReceivedEventHandler(Proc_OutputDataReceived);
Proc.Exited += new EventHandler(Proc_Exited);

Proc.Start();
Proc.BeginErrorReadLine();
Proc.BeginOutputReadLine();

Я могу подозревать, что есть проблема с инструментом обновления. Другие программы с консольным выводом работают нормально.

На временной шкале, когда события запускаются: (= ничего не произошло; | событие сработало)

Should be: ==|==|==|==|==|==|==  
Is: ========|||||||=========||||||=====

Ответы [ 3 ]

6 голосов
/ 19 марта 2011

Вы видите эффект буфера вывода stdout, который использует программа. Это стандартная функция библиотеки времени выполнения C, буферизация включается, когда она обнаруживает, что пишет в канал, а не в консоль. Вместо автоматической очистки после каждого оператора printf () в программе. Размер буфера обычно составляет около 2 килобайт. И вспыхивает только тогда, когда он заполняется. Это значительно повышает эффективность, промывка каждый раз добавляет много накладных расходов. Важно в нормальных сценариях перенаправления, когда вывод записывается в файл или устройство.

Вы можете видеть, куда это идет, сгустки, которые вы видите, являются содержимым этого буфера. Простого решения этой проблемы не существует, в программе требуется операция, чтобы отключить буфер или очистить его там, где это важно. Это всегда, где доллар останавливается, вы не будете делать это, если вы могли бы изменить программу. Вы могли бы подавать консоль с помощью буфера, буферизуя то, что вы получаете из OutputDataReceived, но, возможно, это немного глупо.

Вы не увидите этого эффекта, когда программа отправляет вывод быстрее, чем вы можете его обработать. Что довольно распространено. Он эффективно блокируется, блокируется при ожидании освобождения выходного буфера и быстро заполняет его.

Для этого есть еще одно объяснение: скорость, с которой может работать OutputReceived, зависит также от того, сколько потоков потоков у вас запущено. Если это больше, чем количество ядер процессора, поток tp, который вызывает OutputReceived, может быть задержан кратно 0,5 секунды. Однако вы бы увидели скопление всех программ, которые вы перенаправили.

0 голосов
/ 19 марта 2011

Рассмотрите возможность использования Console.Out.Flush()Console.Error.Flush(), если вы печатаете также в Error Stream).

Насколько я понимаю, обработчики не пишут в командную строку с Console.Out.Write() - они пишут в буфер, который будет распечатан другими обработчиками. При множественных вызовах Console.Out.Write() все буферы записываются не сразу - некоторые тексты остаются в буфере дольше, чем другие. Console.Out.Flush() заставляет систему немедленно записать свой текущий буфер.

0 голосов
/ 19 марта 2011

Я не очень знаком с C #, но вы можете найти полезную информацию по этой проблеме, выполнив поиск в документации по сбросу консоли .

Может быть так:

Console.Out.Flush() 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...