.NETアプリからexeを実行し、標準をストリームリーダーにリダイレクトしようとしています。問題は、私がそうするときです
myprocess.exe >> out.txt
out.txtは14MBに近いです。コマンドラインバージョンを実行すると非常に高速ですが、csharpアプリからプロセスを実行すると、デフォルトのストリームリーダーが4096バイトごとにフラッシュすると思われるため、非常に低速です。
Processオブジェクトのデフォルトのストリームリーダーを変更する方法はありますか?
.NETアプリからexeを実行し、標準をストリームリーダーにリダイレクトしようとしています。問題は、私がそうするときです
myprocess.exe >> out.txt
out.txtは14MBに近いです。コマンドラインバージョンを実行すると非常に高速ですが、csharpアプリからプロセスを実行すると、デフォルトのストリームリーダーが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();
}
編集:私が間違った質問に答えていることに気づきました。私の場合、まだバッファから何も読み取っていなかったため、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();
はい、その通りです。プロセス出力を格納するバッファがあります。通常、一般的なCRT実装では1〜4KBです。1つの小さな詳細:そのバッファは、.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
}
}
これは私のためにうまくいきました:
var sb = new StringBuilder();
while (!proc.StandardOutput.EndOfStream)
{
sb.Append(proc.StandardOutput.ReadToEnd());
proc.StandardOutput.DiscardBufferedData();
}