[英]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.