2010-05-25 87 views
2

我從.NET應用程序運行一個exe文件並試圖將標準重定向到一個流式讀取器。問題是,當我做C#System.Diagnostics.Process將大量數據的標準輸出重定向

myprocess.exe >> out.txt

out.txt是接近14MB。 當我執行命令行版本時,速度非常快,但是當我從csharp應用程序運行該進程時,它非常慢,因爲我相信默認的streamreader會每4096字節刷新一次。

有沒有辦法更改Process對象的默認流讀取器?

回答

5

我還沒有嘗試過,但它看起來像異步方法可能會提供更好的性能。代替使用process.StandardOutput,請嘗試使用此方法:

Process process = Process 
    .Start(new ProcessStartInfo("a.exe"){RedirectStandardOutput = true}); 
if (process != null) 
{ 
    process.OutputDataReceived += ((sender, e) => 
            { 
             string consoleLine = e.Data; 
             //handle data 
            }); 
    process.BeginOutputReadLine(); 
} 
+0

天才!謝謝! – Matt 2010-05-25 23:06:38

+0

非常感謝。 – mitchellt 2014-04-15 19:02:58

3

是的,這是正確的。有緩衝區,它存儲過程輸出,通常在1到4KB的普通CRT實現中。一個小細節:該緩衝區位於您啓動的進程中,而不是.NET程序。

當您重定向到文件時,沒有什麼特別的事情需要發生,CRT直接寫入它。但是,如果您重定向到您的.NET程序,則輸出將從緩衝區進入管道。然後,需要線程切換到您的程序,以便您可以清空管道。來回700次。

是的,不是很快。雖然很容易修復,但在您運行的程序中調用setvbuf()以增加stdout和stderr輸出緩衝區大小。然後再一次,這需要該程序的源代碼。

預測到一個問題:也許你應該使用cmd.exe/c來重定向到一個文件,然後讀取文件。

1

Process類直接公開stdout流,所以你應該能夠以任何你喜歡的速度閱讀它。最好是以小塊讀取它,並避免調用ReadToEnd。

例如:

using(StreamReader sr = new StreamReader(myProcess.StandardOutput)) 
{ 
    string line; 
    while((line = sr.ReadLine()) != null) 
    { 
    // do something with line 
    } 
} 
2

編輯:剛剛意識到我回答錯誤的問題。在我的情況下,stdout緩衝區已滿並且WaitForExit()永遠被阻塞,因爲沒有任何內容正在從緩衝區中讀取。所以如果你有這個問題,那麼這裏有一個解決方案。 ;)

這是我第一天用C#所以請理解,這可能不是最好的解決方案,並且可能無法正常工作。但它在我測試過的2x中起作用。 ;)這是同步的,只需在WaitForExit()之前開始將重定向的stdout/stderr寫入文件即可。這樣WaitForExit()不會阻塞等待stdout緩衝區被清空。

 string str_MyProg = "my.exe"; 
     string str_CommandArgs = " arg1 arg2"' 
     System.Diagnostics.ProcessStartInfo procStartInfo = new System.Diagnostics.ProcessStartInfo(str_MyProg, str_CommandArgs); 

     procStartInfo.RedirectStandardError = true; 
     procStartInfo.RedirectStandardOutput = true; // Set true to redirect the process stdout to the Process.StandardOutput StreamReader 
     procStartInfo.UseShellExecute = false; 
     procStartInfo.CreateNoWindow = true;   // Do not create the black window 

     // Create a process, assign its ProcessStartInfo and start it 
     System.Diagnostics.Process myProcess = new System.Diagnostics.Process(); 
     myProcess.StartInfo = procStartInfo; 
     myProcess.Start(); 

     // Dump the output to the log file 
     string stdOut = myProcess.StandardOutput.ReadToEnd(); 
     StreamWriter logFile = new StreamWriter("output.txt"); 
     logFile.Write(stdOut); 
     logFile.Close(); 

     myProcess.WaitForExit();   
+0

查看你的代碼,特別是StandardOutput和StandardError的重定向,讓我想起了MSDN上的這個頁面(http://msdn.microsoft.com/en-us/library/system.diagnostics.process.standardoutput%28v=vs .71%29.aspx)他們描述了在這種情況下可能出現的僵局。另一方面,你不讀標準錯誤,所以也許這不是問題。 – Spaceghost 2011-12-30 20:56:52

相關問題