我在'wave'中返回控制台输出时遇到问题。例如,控制台每秒输出一些东西,例如事件每分钟触发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: ========|||||||=========||||||=====
答案 0 :(得分:6)
您正在看到程序正在使用的stdout输出缓冲区的效果。这是C运行时库的标准功能,当检测到缓冲区正在写入管道而不是控制台时,会启用缓冲。而不是在程序中的每个printf()语句之后自动刷新。缓冲区通常约为2千字节。只有在它填满时才会被冲洗。这大大提高了效率,每次刷新都会增加很多开销。在正常重定向方案中,将输出写入文件或设备时很重要。
你可以看到它的发展方向,你看到的那块是该缓冲区的内容。没有简单的解决办法,程序中需要手术来禁用缓冲区或在重要的地方冲洗它。这总是在降压停止的地方,如果你可以改变程序你就不会这样做。您可以通过缓冲从OutputDataReceived获得的内容来滴灌您的控制台,但这可能有点愚蠢。
当程序发送输出的速度超过您处理速度时,您将看不到此效果。这很常见。在等待输出缓冲区清空并快速填充它时,它会被有效地限制,阻塞。
还有一个解释,OutputReceived可以触发的速率也取决于你运行的线程池线程数。如果这超过了cpu核心的数量,则调用OutputReceived的tp线程可能会延迟0.5秒的倍数。但是,您会看到重定向的所有程序的聚集。
答案 1 :(得分:0)
我不熟悉C#,但您可以通过搜索 console flushing 的文档找到有关此问题的有用信息。
也许是这样的:
Console.Out.Flush()
答案 2 :(得分:0)
如果您要打印到错误流,请考虑使用Console.Out.Flush()
(和Console.Error.Flush()
。)
据我了解,处理程序不会使用Console.Out.Write()
写入命令行 - 它们正在写入一个缓冲区,其他句柄会打印出来。通过多次调用Console.Out.Write()
,所有的bufferes不会立即写入 - 有些文本留在缓冲区中的时间比其他文本长。 Console.Out.Flush()
强制系统立即写入当前缓冲区。