【发布时间】:2011-04-20 03:29:30
【问题描述】:
这个问题已经被问过不止一次了,但我在这些讨论中都没有找到满意的答案。
我正在启动一个命令行进程,该进程生成对 STDOUT 的实时测量,大约每秒生成一个新结果。使用 System.Diagnostics.Process.StandardOutput 会导致完全不可接受的延迟(超过 20 秒),因为 STDOUT 数据通过 Process.StandardOutput StreamReader 中的 4k 缓冲区工作,并且似乎没有任何方法可以解决这个问题。
调用 Process.StandardOutput.BaseStream.Flush() 不起作用。
我尝试对 Process.StandardOutput 进行逐字节同步读取,但我仍然比实际输出落后 4k。
谁能至少为我验证是否有可能以某种方式克服重定向 STDOUT 时遇到的所有缓冲问题,并在我的应用程序中接收到的数据一出现在 shell 窗口中?我可以从 Process 类继承并更改 StandardOutput 流读取器的行为方式吗?我需要查看原始 WINAPI 调用吗?
无论如何,这必须完成,即使我最终编写了非托管 C++ 来启动任务并使用输出并将其链接。非常感谢任何帮助;我已经无计可施了……
编辑:看来我需要的是可用于 C/C++、Perl、Python 和 Java 的“预期”库的 .Net 实现(这些是我迄今为止发现的唯一库)。有谁知道这样的野兽是否存在?
【问题讨论】:
-
很遗憾你从来没有得到这个问题的好答案......
-
是的。我最终获得了外部命令的源代码,并使用显式 STDOUT 缓冲区刷新重新编译它。不过,我仍然想解决原来的问题。我曾尝试自己编写一个 .Net Expect 实现,但重新编译外部工具似乎是避免老板骂我的更好方法。
-
我一直在努力解决同样的问题。我正在一个单独的线程中读取控制台输出(或者实际上是 2:1 用于 stderr,1 用于 stdout)。事实证明,StandardOutput 仅在您使用
Peek之类的调用时才会缓冲,这将在此过程中返回 -1。如果您只是使用 1 字节的ReadLine或Read,它就可以正常工作,并且您不会遇到缓冲问题。 -
@StefandeBruijn - 不,这在这种情况下不起作用。问题是类似 printf 的函数有两种模式 - 一种“控制台”模式,数据立即输出,另一种“批处理”模式,数据在内部缓冲,因此需要较少的文件 I/O 操作。当外部进程启动并重定向 STDOUT 时,它以“批处理”模式运行 - 使用子进程完全内部的缓冲区。所以,诀窍(我从未想过)是如何欺骗进程以“控制台”模式运行,以便立即打印数据,同时仍然重定向输出。
-
你确定吗?我认为 msbuild 也是如此,但事实证明我当前的解决方案在那里工作,即使所有像
peek和阻塞布尔值这样的“指标”都告诉我它不应该工作。
标签: c# winapi process expect buffering