странное поведение на другом процессе через Process.Start (startInfo) - продолжение - PullRequest
0 голосов
/ 21 декабря 2010

Исходное местоположение ( странное поведение в другом процессе через Process.Start (startInfo) ) не позволяет правильно опубликовать тестовый код. Я должен начать новый вопрос здесь.

Нашему C # (V3.5) необходимо вызвать исполняемый файл C ++ для обработки файла необработанных данных и генерации файлов результатов для нас.

Ранее он работал со следующим кодом (без вызова ReadToEnd () или ReadLine ()):

startInfo.UseShellExecute = false;
startInfo.RedirectStandardError = true;
startInfo.RedirectStandardOutput = true;

Теперь входной файл необработанных данных изменился (больше, чем раньше). Наш призыв к этому исполняемому файлу будет висеть вечно. Основываясь на совете, я добавил ReadToEnd () или ReadLine (), но он будет зависать при этих вызовах. Поэтому я должен либо использовать startInfo.UseShellExecute = true;, либо установить

startInfo.UseShellExecute = false; 
// and with
startInfo.RedirectStandardError = false;
startInfo.RedirectStandardOutput = false;

Не знаю почему?

Ниже приведены случаи, которые я проверял:

  1. рабочий кейс:

    ProcessStartInfo startInfo = new ProcessStartInfo();
    startInfo.CreateNoWindow = true;
    startInfo.UseShellExecute = false;
    startInfo.RedirectStandardError = false;
    startInfo.RedirectStandardOutput = false;
    startInfo.WindowStyle = ProcessWindowStyle.Hidden;
    startInfo.FileName = path;
    startInfo.Arguments = rawDataFileName;
    //startInfo.WorkingDirectory = Util.GetParentDirectory(path, 1);
    try
    {
        Process correctionProcess = Process.Start(startInfo);
        correctionProcess.WaitForExit();
    }
    
  2. рабочий кейс:

    ProcessStartInfo startInfo = new ProcessStartInfo();
    startInfo.CreateNoWindow = true;
    startInfo.UseShellExecute = true;
    startInfo.RedirectStandardError = false;//can be commented out
    startInfo.RedirectStandardOutput = false;//can be commented out
    startInfo.WindowStyle = ProcessWindowStyle.Hidden;
    startInfo.FileName = path;
    startInfo.Arguments = rawDataFileName;
    startInfo.WorkingDirectory = Util.GetParentDirectory(path, 1);
    try
    {
        Process correctionProcess = Process.Start(startInfo);
        correctionProcess.WaitForExit();
    }
    
  3. НЕ рабочий случай (используется ReadLine()):

    ProcessStartInfo startInfo = new ProcessStartInfo();
    startInfo.CreateNoWindow = true;
    startInfo.UseShellExecute = false;
    startInfo.RedirectStandardError = true;
    startInfo.RedirectStandardOutput = true;
    startInfo.WindowStyle = ProcessWindowStyle.Hidden;
    startInfo.FileName = path;
    startInfo.Arguments = rawDataFileName;
    //startInfo.WorkingDirectory = Util.GetParentDirectory(path, 1);
    try
    {
        Process correctionProcess = Process.Start(startInfo);
        while (!correctionProcess.HasExited)
        {
            Log.logItem(LogType.Performance, "read errorMsg @@@@", "DPTM::correctData()", "");
            string errorMsg = correctionProcess.StandardError.ReadLine(); // <-- Hangs here
            Log.logItem(LogType.Performance, "read errorMsg", "DPTM::correctData()", "errorMsg=" + errorMsg);
            string outputMsg = correctionProcess.StandardOutput.ReadLine();
            Log.logItem(LogType.Performance, "read outputMsg", "DPTM::correctData()", "outputMsg=" + outputMsg);
            Thread.Sleep(100);
        }
    }
    
  4. НЕ рабочий случай (используется ReadToEnd()):

    ProcessStartInfo startInfo = new ProcessStartInfo();
    startInfo.CreateNoWindow = true;
    startInfo.UseShellExecute = false;
    startInfo.RedirectStandardError = true;
    startInfo.RedirectStandardOutput = true;
    startInfo.WindowStyle = ProcessWindowStyle.Hidden;
    startInfo.FileName = path;
    startInfo.Arguments = rawDataFileName;
    //startInfo.WorkingDirectory = Util.GetParentDirectory(path, 1);
    try
    {
        Process correctionProcess = Process.Start(startInfo);
        while (!correctionProcess.HasExited)
        {
            Log.logItem(LogType.Performance, "read errorMsg @@@@", "DPTM::correctData()", "");
            string errorMsg = correctionProcess.StandardError.ReadToEnd(); // <-- Hangs here!
            Log.logItem(LogType.Performance, "read errorMsg", "DPTM::correctData()", "errorMsg=" + errorMsg);
            string outputMsg = correctionProcess.StandardOutput.ReadToEnd();
            Log.logItem(LogType.Performance, "read outputMsg", "DPTM::correctData()", "outputMsg=" + outputMsg);
            Thread.Sleep(100);
        }
    }
    
  5. НЕ рабочий случай:

    ProcessStartInfo startInfo = new ProcessStartInfo();
    startInfo.CreateNoWindow = true;
    startInfo.UseShellExecute = false;
    startInfo.RedirectStandardError = true;
    startInfo.RedirectStandardOutput = true;
    startInfo.WindowStyle = ProcessWindowStyle.Hidden;
    startInfo.FileName = path;
    startInfo.Arguments = rawDataFileName;
    //startInfo.WorkingDirectory = Util.GetParentDirectory(path, 1);
    try
    {
        Process correctionProcess = Process.Start(startInfo);
        Log.logItem(LogType.Performance, "read errorMsg @@@@", "DPTM::correctData()", "");
        string errorMsg = correctionProcess.StandardError.ReadToEnd(); // <-- Hangs here!
        Log.logItem(LogType.Performance, "read errorMsg", "DPTM::correctData()", "errorMsg=" + errorMsg);
        string outputMsg = correctionProcess.StandardOutput.ReadToEnd();
        Log.logItem(LogType.Performance, "read outputMsg", "DPTM::correctData()", "outputMsg=" + outputMsg);
        correctionProcess.WaitForExit();
    }
    

1 Ответ

0 голосов
/ 21 декабря 2010

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

Глядя на ваш пример MSDN: вау, этот пример действительно сбивает с толку ... Было бы легче следовать, если бы они просто ограничивали его std outили стандартная ошибка.

Вам необходимо сначала установить обработчик данных

correctionProcess.OutputDataReceived += new DataReceivedEventHandler(OutputDataHandler);

, а затем вызвать

p.BeginOutputReadLine();

Так же, как комментарий [смущает] советует не пытаться читатьвыход там.Вместо этого используйте обработчик.

    private void OutputDataHandler(object sendingProcess, DataReceivedEventArgs data)
    {
        if (data.Data != null)
        {
            // append data.Data to your internal buffer (StringBuilder?)
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...