简体   繁体   English

如何有效地从儿童Pocress的标准品中读取长行?

[英]How to read long lines from child pocress' stdout in an efficient way?

Note: This question has changed significantly since the first version, so some comments or answers could seem weird. 注意:自第一个版本以来,此问题已发生重大变化,因此某些评论或答案似乎很奇怪。 Please, check the edit history if something seems weird. 请检查编辑历史记录,看是否有些奇怪。

I am launching a child process from a C# class library. 我正在从C#类库启动子进程。

I am using Process.BeginOutputReadLine() to read the output/error in an asynchronous way. 我正在使用Process.BeginOutputReadLine()以异步方式读取输出/错误。 I thought it didn't work with very long lines, but the problem seems to be that it's not scalable. 我以为它不能用于很长的行,但是问题似乎在于它不可扩展。 In my computer, a 128 kb line is processed instantly, a 512 kb line seems to take around one minute, 1 mb seems to take several minutes, and I've been around two hours waiting for a 10 mb line to be processed, and it was still working when I cancelled it. 在我的计算机中,一条128 kb的线被立即处理,一条512 kb的线似乎需要一分钟,一mb的似乎要花费几分钟,而我已经等待了大约2个小时才等待处理10 mb的线。当我取消它时它仍在工作。

It seems easy to fix reading directly from the StandardOutput and StandardError streams, but the data from those streams seems to be buffered. 直接从StandardOutput和StandardError流中读取数据似乎很容易解决,但是这些流中的数据似乎已被缓冲。 If I get wnough data from stdout to fill the buffer, and then some more data from stderr, I can't find a way to check if there's data pending in one of them, and if I try to read from stderr, it will hang forever. 如果我从stdout获取足够的数据来填充缓冲区,然后从stderr获得更多数据,则无法找到一种方法来检查其中是否有待处理的数据,并且如果我尝试从stderr读取数据,则它将挂起永远。 Why is this happening, what am I doing wrong, and what's the right way to do this? 为什么会发生这种情况,我做错了什么,做这件事的正确方法是什么?

Some code samples to illustrate what I'm trying to achieve. 一些代码示例说明了我要实现的目标。

Program1 : Program1

  // Writes a lot of data to stdout and stderr static void Main(string[] args) { int numChars = 512 * 1024; StringBuilder sb = new StringBuilder(numChars); String s = "1234567890"; for (int i = 0; i < numChars; i++) sb.Append(s[i % 10]); int len = sb.Length; Console.WriteLine(sb.ToString()); Console.Error.WriteLine(sb.ToString()); } 

Program2 : Program2

  // Calls Program1 and tries to read its output. static void Main(string[] args) { StringBuilder sb = new StringBuilder(); StringBuilder sbErr = new StringBuilder(); proc.StartInfo.CreateNoWindow = true; proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; proc.StartInfo.UseShellExecute = false; proc.StartInfo.RedirectStandardError = true; proc.StartInfo.RedirectStandardOutput = true; proc.StartInfo.RedirectStandardInput = false; proc.StartInfo.Arguments = ""; proc.StartInfo.FileName = "program1.exe"; proc.ErrorDataReceived += (s, ee) => { if (ee.Data != null) sbErr.AppendLine(ee.Data); }; proc.OutputDataReceived += (s, ee) => { if (ee.Data != null) sb.AppendLine(ee.Data); }; proc.Start(); proc.BeginOutputReadLine(); proc.BeginErrorReadLine(); proc.WaitForExit(); } 

Program1 has a constant that allows to set the size of data to generate, and Program2 launches Program1 and tries to read the data. Program1具有一个常数,该常数允许设置要生成的数据大小,而Program2启动Program1并尝试读取数据。 I should expect the time to grow linearly with size, but it seems much worse than that. 我应该期望时间随着大小线性增长,但是似乎比那差得多。

I hope i understand your problem. 希望我能理解您的问题。 the application hangs on Process.WaitForExit() because this is what Process.WaitForExit() : it waits for the process to exit . 应用程序挂在Process.WaitForExit()因为这就是Process.WaitForExit()它等待进程退出

you might want to call it in a new thread: int your method that create the process: 您可能想在新线程中调用它:int创建过程的方法:

    Thread trd = new Thread(new ParameterizedThreadStart(Start));
     trd.Start();

and add this method: 并添加此方法:

  private void Start(object o)
  {
     ((Process)o).WaitForExit();
     // your code after process ended
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM