【问题标题】:How to disable output buffering in Process.StandardOutput如何在 Process.StandardOutput 中禁用输出缓冲
【发布时间】: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 字节的 ReadLineRead,它就可以正常工作,并且您不会遇到缓冲问题。
  • @StefandeBruijn - 不,这在这种情况下不起作用。问题是类似 printf 的函数有两种模式 - 一种“控制台”模式,数据立即输出,另一种“批处理”模式,数据在内部缓冲,因此需要较少的文件 I/O 操作。当外部进程启动并重定向 STDOUT 时,它以“批处理”模式运行 - 使用子进程完全内部的缓冲区。所以,诀窍(我从未想过)是如何欺骗进程以“控制台”模式运行,以便立即打印数据,同时仍然重定向输出。
  • 你确定吗?我认为 msbuild 也是如此,但事实证明我当前的解决方案在那里工作,即使所有像 peek 和阻塞布尔值这样的“指标”都告诉我它不应该工作。

标签: c# winapi process expect buffering


【解决方案1】:

“[我]有没有办法启动它,以至于它没有意识到它正在被重定向?”是的:这正是 Expect 的领域。我知道没有 .Net 实现;不过这肯定是可行的……

【讨论】:

  • 由于 Windows 内部的工作方式非常具有挑战性! (嗯,不是在 Unix 上的 Mono 上,你可以访问真正的虚拟终端,但那是另一回事。)Windows 的 Expect 使用某种时髦的调试模式来使这一切正常工作,而 AIUI 是一个非常糟糕的 hack。在子进程中使用实际的expect 本身(运行unbuffer 脚本)可能会更容易;是的,它使部署变得更加困难,但它确实有很好的工作机会。除了telnet.exe;这是一个特殊的(而且非常糟糕的)案例。
猜你喜欢
  • 2010-09-11
  • 2012-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多