Pascal StdIn / StdOut管道

时间:2015-10-01 04:00:16

标签: pipe stdout stdin pascal

我正在尝试编写一个由另一个程序作为进程启动的Pascal(Lazarus / FPC)程序。调用者(竞技场国际象棋GUI)使用StdIn和StdOut与我的程序进行对话。

首先,我在程序中使用READLN来获取GUI和WRITELN发送的文本命令以回复它们。这很有效,但是如果READLN必须等待来自GUI的输入,我的程序将停止做任何事情。由于我希望程序继续工作并且只在他们到达时处理命令,我不得不改变它。

所以我改变了使用的代码:

...
var   inpStream        : TInputPipeStream;
...
inpStream := TInputPipeStream.Create(StdInputHandle);
...
if inpStream.NumBytesAvailable > 0 then begin
    SetLength(s_buffer, inpStream.NumBytesAvailable);
    inpStream.Read(s_buffer[1], length(s_buffer));
end;
...

这非常有效,因为它不再暂停阅读。但随后WRITELN停止工作:没有任何东西被发送回GUI。我想也许这会有所帮助:

...
var inpStream        : TInputPipeStream;
    outStream        : TOutputPipeStream;
...
inpStream := TInputPipeStream.Create(StdInputHandle);
outStream := TOutputPipeStream.Create(StdOutputHandle);
...
if inpStream.NumBytesAvailable > 0 then begin
    SetLength(s_buffer, inpStream.NumBytesAvailable);
    inpStream.Read(s_buffer[1], length(s_buffer));
end;
...
outStream.Write(s_buffer, length(s_buffer));

但是这会让它变得更糟,因为现在它不会读或写任何东西。那么如何在保持写入StdOut的能力的同时在StdIn上有非阻塞输入?

2 个答案:

答案 0 :(得分:0)

假设您使用Windows,可能这意味着读取输出的程序不能经常读取它(它可以让它大量增加),然后当管道的总大小达到一定大小(通常为几MB)时窗户停止处理。

这是一种新情况,需要深入研究Windows管道和作业控制。在FPC 3.x TProcess中,修复了一些错误,它们是相似的(如果stderr也没有定期处理,管道处理会停止,请参阅内部命令代码)。

如果接收程序没有处理stderr,请不要使用它。

答案 1 :(得分:0)

嗯,这太尴尬了!由于我的程序中存在逻辑错误,因此未正确发送对GUI的回复。感谢Marco的答案,是的,我正在使用Windows。事实证明:

READLN / WRITELN有效,但在读取READLN之前停止程序。

TInputPipeStream / WRITELN在不停止程序的情况下工作,因此解决了我的问题。

TInputStream / TOutputStream似乎没有合作,我不知道为什么。这是我试图初始化它们的方式还是它们应该是排他性的?