【发布时间】:2011-06-02 13:34:13
【问题描述】:
在 Delphi 7 控制台应用程序中,如何检查 stdin 是否包含一个字符,而不阻塞直到输入一个字符?
我的计划是这个控制台程序将由一个 GUI 程序执行,它的标准输入将由 GUI 程序写入。
所以我希望我的控制台应用程序定期检查标准输入,但我找不到不阻塞的方法。
我查看了this answer,它为我提供了一个指向标准输入的流,但据我所知,仍然无法“窥视”。
【问题讨论】:
在 Delphi 7 控制台应用程序中,如何检查 stdin 是否包含一个字符,而不阻塞直到输入一个字符?
我的计划是这个控制台程序将由一个 GUI 程序执行,它的标准输入将由 GUI 程序写入。
所以我希望我的控制台应用程序定期检查标准输入,但我找不到不阻塞的方法。
我查看了this answer,它为我提供了一个指向标准输入的流,但据我所知,仍然无法“窥视”。
【问题讨论】:
我想你已经找到了阅读标准输入的正确方法。它的目的是在没有更多内容可读取时进行阻止。
处理此问题的标准方法是使用单独的线程来处理管道。当它从标准输入接收到新数据时,它会向处理线程发出信号,例如使用消息传递机制。
说了这么多,如果你真的想投票,你可以调用 PeekNamedPipe 来检查管道中是否有数据。
【讨论】:
正如另一个答案所说,您可以使用线程,但即便如此,您也可能会遇到问题(使用线程方法),除非您还调查重叠 IO。
我通常使用带串行端口的重叠 IO 而不是标准输入,其中通常需要“如果一个字符准备好就读取一个字符”,而非阻塞 IO 是一种常用的工作方式。您应该能够适应here 所示的技术。但是,如果我正在编写一个由键盘驱动的应用程序(而不是纯粹由重定向到标准输入的文件驱动),我会放弃 StdIN,并使用 CRT 类型的单元。因此,如果您不介意放弃 StdIn,而只是想要一个键盘驱动的输入模型,您可以查看基于控制台的 API 并放弃非常有限的 StdIn 功能。有关使用 Win32 控制台 API 的“kbhit”函数示例,请参阅here。
【讨论】:
没有其他方法(据我所知),从单独线程内的管道读取。否则,正如您已经看到的,readfile 操作将阻塞。我写了一个示例如何做到这一点,示例项目也可用:redirect stdoutput
编辑:好吧,再次阅读您的问题,我知道您的问题在于控制台程序,而不是调用应用程序。我想知道您的控制台应用程序期望什么,通常控制台应用程序知道何时需要输入并且在用户输入此信息之前无法继续。需要检查出口吗?
【讨论】:
对于流,如果你 .Read() 函数结果是读取的字节数,如果那里什么都没有,即使你要求更多,它也会为零。来自 Classes.TStream.Read 的 Delphi 帮助:
Read 用于从流中读取的字节数不一定固定的情况。它尝试将最多 Count 个字节读入缓冲区并返回实际读取的字节数。
【讨论】: