Анализатор обнаружил, что результаты обработки вывода процесса могут быть использованы до завершения всех операций их формирования. В этом случае приложение будет использовать выходные данные процесса в некорректном или неполном виде.
Рассмотрим пример:
public void Run()
{
var process = new Process();
process.StartInfo.FileName = GetProcessFile();
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
StringBuilder data = new StringBuilder();
process.OutputDataReceived +=
(sender, args) => data.AppendLine(args.Data); // <=
process.Start();
process.BeginOutputReadLine();
WriteData(data.ToString()); // <=
}
Код в данном примере запускает процесс, сохраняет его вывод в переменную 'data', после чего собранные результаты передаются в метод 'WriteData'. Здесь возможна ситуация, при которой вызов 'data.ToString' будет выполнен до полной обработки всего вывода процесса. К примеру, если процесс выводит несколько строк, то к моменту вызова 'ToString' не все из них могут быть добавлены в переменную 'data'.
Для решения проблемы необходимо убедиться, что обработка всего вывода процесса была завершена. Для этого можно вызвать метод 'WaitForExit' без аргументов:
public void Run()
{
var process = new Process();
process.StartInfo.FileName = GetProcessFile();
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
StringBuilder data = new StringBuilder();
process.OutputDataReceived +=
(sender, args) => data.AppendLine(args.Data);
process.Start();
process.BeginOutputReadLine();
process.WaitForExit();
WriteData(data.ToString());
}
Такой вызов 'WaitForExit' возвращает управление только после того, как обработка вывода будет завершена. Обратите внимание, что вызов перегрузки 'WaitForExit(Int32)' не обладает данной особенностью. Поэтому следующий код может отрабатывать некорректно:
public void Run()
{
var process = new Process();
....
StringBuilder data = new StringBuilder();
process.OutputDataReceived +=
(sender, args) => data.AppendLine(args.Data); // <=
process.Start();
process.BeginOutputReadLine();
if (process.WaitForExit(3000))
{
WriteData(data.ToString()); // <=
}
else
{
.... // throw timeout error
}
}
В данном примере получение значения из переменной 'data' производится после того, как процесс завершил работу. Тем не менее, обработка вывода процесса может быть не завершена к моменту вызова 'ToString'. Такое поведение описано в документации к методу 'WaitForExit'. Для того чтобы обработка была гарантированно завершена, необходимо дополнительно вызвать метод без аргументов:
public void Run()
{
var process = new Process();
....
StringBuilder data = new StringBuilder();
process.OutputDataReceived +=
(sender, args) => data.AppendLine(args.Data);
process.Start();
process.BeginOutputReadLine();
if (process.WaitForExit(3000))
{
process.WaitForExit();
WriteData(data.ToString());
}
else
{
.... // throw timeout error
}
}
Данная диагностика классифицируется как: