通过Process.Start(startInfo)在另一个进程上的奇怪行为 - 继续

时间:2010-12-21 18:40:53

标签: c# .net process

原始位置(strange behaviour on another process via 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 :(得分:0)

您在错误/输出缓冲区上死锁。您正在等待该过程完成时,您的第二个进程正在等待缓冲区释放。您需要异步读取输出/错误流以防止这种情况发生。

查看您的MSDN示例:哇,该示例真的令人困惑......如果将它们限制为std out或std错误,那么它会更容易理解。

您需要先设置数据处理程序

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?)
        }
    }