Перенаправление стандартного вывода в .NET с помощью BinaryReader - обнаружение EOS / форсирование тайм-аута - PullRequest
3 голосов
/ 20 апреля 2011

Я перенаправляю стандартный вывод из Process в приложении C # NET 4, а затем использую BinaryReader в отдельном потоке для его чтения.(Это двоичные данные; фрагменты видео, которые требуют анализа для разделителей)

Все работает нормально, пока процесс не выводит последний байт, после чего BinaryReader зависает, блокируя ReadBytes (int). Это мне не подходит;Мне нужно знать, когда поток достиг конца, чтобы записать окончательный кусок данных на диск.

Я бы использовал событие Process.Exited и обработал бы его как эквивалент EOS (затем уничтожил бы поток).Но Process.Exited никогда не вызывается: предположительно, процесс ожидает, пока мое приложение закроет поток, прежде чем оно умрет.

К сожалению, этот вопрос , кажется, указывает на то, что любой вызов кСвойства уровня StandardOutput, такие как StandardOutput.EndOfStream, будут вызывать доступ к StreamReader по умолчанию для StandardOutput, поэтому я предполагаю, что этот подход отсутствует.

Есть ли простой способ определить конецпоток или сделать время ожидания BinaryReader?

{
  runningProcess.Start();

 // Read standard output on a new thread
 thrdReadStandardOut = new Thread(new ThreadStart(ReadStandardOutput));
 thrdReadStandardOut.Start(); 

}

...

void ReadStandardOutput()
        {
            Monitor.Enter(runningProcess);  // keep this section thread safe

            var br = new BinaryReader(runningProcess.StandardOutput.BaseStream);
            bool abort = false;

            while (!abort)
            {
                try
                {
                    byte[] bytes = br.ReadBytes(256);

                    if (StandardOutputReceived != null)
                        StandardOutputReceived(this, new GenericEventArgs<byte[]>(bytes));
                }
                catch (EndOfStreamException)
                {
                    abort = true;
                }
            }

            Monitor.Exit(runningProcess);
        }

1 Ответ

1 голос
/ 21 апреля 2011

Событие Process.Exited будет инициировано только в том случае, если для Process.EnableRaisingEvents установлено значение true. Если вы сделаете это, вы должны будете получать уведомления о завершении процесса через Process.Exited или синхронный метод Process.WaitForExit.

Если вы все еще не получаете это событие, посмотрите, завершается ли ваш дочерний процесс изящно (хотя даже тогда я все еще ожидал бы, что Exited сработает).

...