Правильный способ обработки стандартной ошибки и вывода из программы, когда появляется через класс процесса из C#?

StackOverflow https://stackoverflow.com/questions/4137346

Вопрос

Я прочитал документацию для Process.standardOutput, который имеет эту цитату:

Условие тупика может привести к тому, что родительский процесс вызовет p.waitforexit до p.standardoutput.readtoend, а дочерний процесс записывает достаточно текста, чтобы заполнить перенаправленный поток.

Так что мне интересно. Как правильный способ сделать это, если я также боюсь, что StandardError может быть заполнен в некоторых сценариях?

Должен ли я использовать цикл для альтернативного чтения из стандартного вывода и ошибок, чтобы избежать либо заполнения, либо этот простой код достаточно:

string error = proc.StandardError.ReadToEnd();
string output = proc.StandardOutput.ReadToEnd();
bool didFinish = proc.WaitForExit(60000);

Отредактировано после того, как некоторые ответы были опубликованы

Так это правильный подход?

var output = new StringBuilder();
proc.OutputDataReceived += (s, e) => output.Append(e.Data);
proc.BeginOutputReadLine();
string error = proc.StandardError.ReadToEnd();
bool didFinish = proc.WaitForExit(60000);

А потом я использую контент StringBuilder, только если процесс фактически завершился.

Это правильный подход тогда?

Это было полезно?

Решение

Ваш пример кода может вызвать ситуацию тупика, когда было что -то написано StandardOutput и не для StandardError. Анкет Самый следующий пример из документации, которую вы связали, так же сильно.

По сути, то, что я бы порекомендовал, использует асинхронные чтения на обоих потоках, чтобы заполнить буфер по мере написания потоков, а затем вызовут WaitForExit.

Другие советы

Проблема возникает из -за того, что дочерний процесс записывает свой стандартный выход и стандартную ошибку в пару труб, которые получают конечный буфер у ОС. Если родитель не активно читает их обоих, то он может заполнить. Когда труба заполняется, любые последующие записи к ней блокируются.

В вашем примере вы читаете все StandardError тогда все StandardOutput. Анкет Это работает нормально, если дочерний процесс только записывает немного данных StandardError и/или StandardOutput. Анкет Это проблема, если дочерний процесс хочет написать много данных StandardOutput. Анкет Пока родительский процесс ждет использования данных из StandardError, дочерний процесс занят заполнением StandardOutput буфер.

Самый безопасный способ - прочитать из стандартной и стандартной ошибки одновременно. Есть несколько способов сделать это:

  • Породить отдельные потоки и позвонить ReadToEnd на каждой
  • Использовать BeginRead и EndRead на одной ветке
  • Добавить обработчиков на Process.ErrorDataReceived и Process.OutputDataReceived События, затем позвоните Process.BeginErrorReadLine и Process.BeginOutputReadLine.
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top