我從.NET應用程序運行一個exe文件並試圖將標準重定向到一個流式讀取器。問題是,當我做C#System.Diagnostics.Process將大量數據的標準輸出重定向
myprocess.exe >> out.txt
out.txt是接近14MB。 當我執行命令行版本時,速度非常快,但是當我從csharp應用程序運行該進程時,它非常慢,因爲我相信默認的streamreader會每4096字節刷新一次。
有沒有辦法更改Process對象的默認流讀取器?
我從.NET應用程序運行一個exe文件並試圖將標準重定向到一個流式讀取器。問題是,當我做C#System.Diagnostics.Process將大量數據的標準輸出重定向
myprocess.exe >> out.txt
out.txt是接近14MB。 當我執行命令行版本時,速度非常快,但是當我從csharp應用程序運行該進程時,它非常慢,因爲我相信默認的streamreader會每4096字節刷新一次。
有沒有辦法更改Process對象的默認流讀取器?
我還沒有嘗試過,但它看起來像異步方法可能會提供更好的性能。代替使用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();
}
是的,這是正確的。有是緩衝區,它存儲過程輸出,通常在1到4KB的普通CRT實現中。一個小細節:該緩衝區位於您啓動的進程中,而不是.NET程序。
當您重定向到文件時,沒有什麼特別的事情需要發生,CRT直接寫入它。但是,如果您重定向到您的.NET程序,則輸出將從緩衝區進入管道。然後,需要線程切換到您的程序,以便您可以清空管道。來回700次。
是的,不是很快。雖然很容易修復,但在您運行的程序中調用setvbuf()以增加stdout和stderr輸出緩衝區大小。然後再一次,這需要該程序的源代碼。
預測到一個問題:也許你應該使用cmd.exe/c來重定向到一個文件,然後讀取文件。
Process類直接公開stdout流,所以你應該能夠以任何你喜歡的速度閱讀它。最好是以小塊讀取它,並避免調用ReadToEnd。
例如:
using(StreamReader sr = new StreamReader(myProcess.StandardOutput))
{
string line;
while((line = sr.ReadLine()) != null)
{
// do something with line
}
}
編輯:剛剛意識到我回答錯誤的問題。在我的情況下,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();
查看你的代碼,特別是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
天才!謝謝! – Matt 2010-05-25 23:06:38
非常感謝。 – mitchellt 2014-04-15 19:02:58