2010-12-21 114 views
0

原始位置(strange behaviour on another process via Process.Start(startInfo))不允許我正確地發佈測試代碼。我必須在這裏開始一個新的問題。通過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(); 
    } 
    

回答

0

你在錯誤/輸出緩衝陷入僵局。您的第二個進程正在等待緩衝區在您等待該進程完成時釋放。您需要異步讀取輸出/錯誤流以防止出現這種情況。

看看你的MSDN示例:哇,這個示例真的讓人困惑......如果他們僅僅將它限制在標準輸出或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?) 
     } 
    } 
+0

以下是Miscrosoft的示例代碼。我的情況5和它一樣。它在這裏:http://msdn.microsoft.com/en-us/library/system.diagnostics.process.standarderror(v=VS.90).aspx – 5YrsLaterDBA 2010-12-21 19:06:03