C#System.Diagnostics。进程重定向标准输出以处理大量数据

问题描述 投票:2回答:5

我从.NET应用程序运行exe,并尝试将标准重定向到流阅读器。问题是当我这样做

myprocess.exe >> out.txt

out.txt接近14mb。当我执行命令行版本时,它的速度非常快,但是当我从csharp应用程序运行该过程时,速度却非常慢,因为我相信默认的流读取器会每4096个字节刷新一次。

是否可以更改Process对象的默认流读取器?

c# .net streamreader
5个回答
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();
}

4
投票

编辑:刚意识到我在回答错误的问题。在我的情况下,stdout缓冲区已满,并且WaitForExit()永远处于阻塞状态,因为尚未从缓冲区读取任何内容。因此,如果您有那个问题,那么这里是一个解决方案。 ;)

这是我使用C#的第一天,因此请理解,这可能不是最佳解决方案,并且可能并不总是有效。但是它可以在我测试过的2倍中工作。 ;)这是同步的,只需在开始WaitForExit()之前就开始将重定向的stdout / stderr写入文件。这样,WaitForExit()不会阻止等待标准缓冲区清空。

      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();          

3
投票

是的,那是对的。有一个缓冲区,用于存储过程输出,在常见的CRT实现中通常在1-4KB之间。一个小细节:该缓冲区位于您启动的进程中,而不是.NET程序。当您重定向到文件时,CRT会直接写入该文件,没有什么特别的需要。但是,如果您重定向到.NET程序,则输出将从缓冲区进入管道。然后需要将线程切换到

your

程序,以便可以清空管道。来回好700次。是,不是很快。尽管很容易解决,但是在您正在运行的程序中调用setvbuf()可以增加stdout和stderr输出缓冲区的大小。再说一次,这需要拥有该程序的源代码。

预计会出现问题:也许您应该使用cmd.exe / c来获取到文件的重定向,然后读取文件。


1
投票
Process类直接公开标准输出流,因此您应该能够以自己喜欢的速度阅读它。最好以小块形式阅读它,避免调用ReadToEnd。

0
投票
这对我有用:
© www.soinside.com 2019 - 2024. All rights reserved.