2

.NETアプリからexeを実行し、標準をストリームリーダーにリダイレクトしようとしています。問題は、私がそうするときです

myprocess.exe >> out.txt

out.txtは14MBに近いです。コマンドラインバージョンを実行すると非常に高速ですが、csharpアプリからプロセスを実行すると、デフォルトのストリームリーダーが4096バイトごとにフラッシュすると思われるため、非常に低速です。

Processオブジェクトのデフォルトのストリームリーダーを変更する方法はありますか?

4

5 に答える 5

6

試したことはありませんが、非同期メソッドの方がパフォーマンスが向上する可能性があります。を使用する代わりに、代わりに次の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();
}
于 2010-05-25T22:58:14.493 に答える
4

編集:私が間違った質問に答えていることに気づきました。私の場合、まだバッファから何も読み取っていなかったため、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();          
于 2011-10-28T21:30:17.287 に答える
3

はい、その通りです。プロセス出力を格納するバッファがあります。通常、一般的なCRT実装では1〜4KBです。1つの小さな詳細:そのバッファは、.NETプログラムではなく、開始するプロセスにあります。

ファイルにリダイレクトするときに特別なことをする必要はありません。CRTがファイルを直接書き込みます。ただし、.NETプログラムにリダイレクトすると、出力はバッファーからパイプに送られます。次にプログラムへのスレッドスイッチが必要になるため、パイプを空にすることができます。700回前後に良い。

はい、速くはありません。ただし、簡単に修正できますが、実行しているプログラムでsetvbuf()を呼び出して、stdoutおよびstderrの出力バッファーサイズを増やします。繰り返しになりますが、そのプログラムのソースコードを用意する必要があります。

その問題を予測する:ファイルへのリダイレクトを取得するためにcmd.exe / cを使用してから、ファイルを読み取る必要があるかもしれません。

于 2010-05-25T23:00:16.330 に答える
1

Processクラスはstdoutストリームを直接公開するため、好きなペースで読み取ることができるはずです。小さなチャンクでそれを読み、ReadToEndを呼び出さないようにするのがおそらく最善です。

例えば:

using(StreamReader sr = new StreamReader(myProcess.StandardOutput))
{
  string line;
  while((line = sr.ReadLine()) != null)
  {
    // do something with line
  }
}
于 2010-05-25T23:02:13.510 に答える
0

これは私のためにうまくいきました:

            var sb = new StringBuilder();
            while (!proc.StandardOutput.EndOfStream)
            {
                sb.Append(proc.StandardOutput.ReadToEnd());
                proc.StandardOutput.DiscardBufferedData();
            }
于 2020-02-12T13:48:49.133 に答える