注意:这个问题自第一个版本以来发生了很大变化,所以一些评论或答案可能看起来很奇怪。如果有什么奇怪的地方,请检查编辑历史。
我正在从 C# 类库启动一个子进程。
我Process.BeginOutputReadLine()
用来以异步方式读取输出/错误。我认为它不适用于很长的行,但问题似乎是它不可扩展。在我的电脑中,一条 128 kb 的线路被立即处理,一条 512 kb 的线路似乎需要大约一分钟,1 mb 的线路似乎需要几分钟,而我等待处理一条 10 mb 的线路大约需要两个小时,并且当我取消它时它仍在工作。
直接从 StandardOutput 和 StandardError 流中修复读取似乎很容易,但来自这些流的数据似乎被缓冲了。如果我从标准输出获得足够的数据来填充缓冲区,然后从标准错误获得更多数据,我无法找到一种方法来检查其中一个是否有待处理的数据,如果我尝试从标准错误读取,它将挂起永远。为什么会发生这种情况,我做错了什么,正确的方法是什么?
一些代码示例来说明我想要实现的目标。
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
:
// 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
有一个常量,允许设置要生成的数据的大小,并Program2
启动Program1
并尝试读取数据。我应该预计时间会随着大小线性增长,但似乎比这更糟。