读取其他进程控制台输出
当控制台输出以“waves”形式返回时,我遇到问题。例如,控制台每秒输出一些内容,例如事件每分钟触发 60 次(所有事件同时发生)。
我的代码:
Process Proc = new Process();
Proc.StartInfo.FileName = SSMS.BinaryDir + "HldsUpdateTool.exe";
Proc.StartInfo.Arguments = "-command update -game tf -dir " + SSMS.RootDir + Key;
Proc.StartInfo.UseShellExecute = false;
Proc.StartInfo.RedirectStandardOutput = true;
Proc.StartInfo.RedirectStandardError = true;
Proc.EnableRaisingEvents = true;
Proc.StartInfo.CreateNoWindow = false;
Proc.ErrorDataReceived += new DataReceivedEventHandler(Proc_ErrorDataReceived);
Proc.OutputDataReceived += new DataReceivedEventHandler(Proc_OutputDataReceived);
Proc.Exited += new EventHandler(Proc_Exited);
Proc.Start();
Proc.BeginErrorReadLine();
Proc.BeginOutputReadLine();
我可能怀疑更新工具有问题。其他带有控制台输出的程序工作正常。
在事件触发的时间线中:( = 没有发生;| 事件已触发)
Should be: ==|==|==|==|==|==|==
Is: ========|||||||=========||||||=====
I have problem when console output is returned in 'waves'. For example console outputs something every second, and for example event triggers 60 times every minute (all events at he same time).
My code:
Process Proc = new Process();
Proc.StartInfo.FileName = SSMS.BinaryDir + "HldsUpdateTool.exe";
Proc.StartInfo.Arguments = "-command update -game tf -dir " + SSMS.RootDir + Key;
Proc.StartInfo.UseShellExecute = false;
Proc.StartInfo.RedirectStandardOutput = true;
Proc.StartInfo.RedirectStandardError = true;
Proc.EnableRaisingEvents = true;
Proc.StartInfo.CreateNoWindow = false;
Proc.ErrorDataReceived += new DataReceivedEventHandler(Proc_ErrorDataReceived);
Proc.OutputDataReceived += new DataReceivedEventHandler(Proc_OutputDataReceived);
Proc.Exited += new EventHandler(Proc_Exited);
Proc.Start();
Proc.BeginErrorReadLine();
Proc.BeginOutputReadLine();
I might suspect that there is problem with update tool. Other programs with console output work fine.
In time line when events are triggered: ( = nothing happened; | event fired )
Should be: ==|==|==|==|==|==|==
Is: ========|||||||=========||||||=====
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您正在看到程序正在使用的 stdout 输出缓冲区的效果。这是 C 运行时库的标准功能,当检测到正在写入管道而不是控制台时,会启用缓冲。而不是在程序中的每个 printf() 语句之后自动刷新。缓冲区通常约为 2 KB。并且只有在充满时才会被冲洗。这样就大大提升了效率,每次刷新都会增加很多开销。当输出写入文件或设备时,在正常重定向场景中很重要。
您可以看到它的去向,您看到的块就是该缓冲区的内容。对此没有简单的修复方法,需要在程序中进行手术以禁用缓冲区或在重要的地方刷新它。这总是责任停止的地方,如果你可以改变程序,你就不会这样做。您可以通过缓冲从 OutputDataReceived 获得的内容来滴灌控制台,但这可能有点愚蠢。
当程序发送输出的速度比您处理它的速度快时,您不会看到这种效果。这很常见。它有效地受到限制,在等待输出缓冲区清空并快速填充它时阻塞。
对此还有一种解释,OutputReceived 的触发速率还取决于您正在运行的线程池线程数量。如果这超过了 cpu 核心的数量,则调用 OutputReceived 的 tp 线程可能会延迟 0.5 秒的倍数。然而,您会看到您重定向的所有程序都聚集在一起。
You are seeing the effect of the stdout output buffer that the program is using. This is a standard feature of the C runtime library, buffering is enabled when it detects that it is writing to a pipe instead of the console. Instead of automatically flushing after each printf() statement in the program. The buffer is usually around 2 kilobytes. And only gets flushed when it fills up. This greatly enhances efficiency, flushing every time adds a lot of overhead. Important in normal redirect scenarios, when output is written to a file or device.
You can see where this is going, the clumps you see are the content of that buffer. There is no simple fix for this, surgery is required in the program to disable the buffer or flush it where it matters. That's invariably where the buck stops, you would not be doing this if you could alter the program. You could drip-feed your console by buffering what you get from OutputDataReceived but that's a bit silly perhaps.
You won't see this effect when the program is sending output faster than you can process it. Which is pretty common. It effectively gets throttled, blocking while waiting for the output buffer to empty and quickly filling it back up.
There's one more explanation for this, the rate at which OutputReceived can fire also depends on how many threadpool threads you've got running. If that's more than the number of cpu cores, the tp thread that calls OutputReceived may be delayed by a multiple of 0.5 seconds. You would however see the clumping on all programs you redirect.
我对 C# 一点也不熟悉,但您可能会通过搜索控制台刷新文档来找到有关此问题的有用信息。
也许是这样的:
I'm in no way familiar with C# but you might find useful information regarding this issue by searching the docs for console flushing.
Maybe like this:
考虑使用
Console.Out.Flush()
(如果您也要打印到错误流,请考虑使用Console.Error.Flush()
)。据我了解,处理程序不会使用
Console.Out.Write()
写入命令行 - 它们正在写入其他处理程序将打印出来的缓冲区。通过多次调用Console.Out.Write()
,所有缓冲区都不会立即写入 - 某些文本在缓冲区中保留的时间比其他文本长。Console.Out.Flush()
强制系统立即写入其当前缓冲区。Consider using
Console.Out.Flush()
(andConsole.Error.Flush()
, if you're printing to Error Stream as well).As I understand it, the handlers aren't writing to command line with
Console.Out.Write()
- they're writing to a buffer that something else handles will print out. With multiple calls toConsole.Out.Write()
, the all the bufferes aren't written at once - some texts is left in a buffer longer than others.Console.Out.Flush()
forces the system to write its current buffer immediately.