我正在尝试编写一个由另一个程序作为进程启动的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上有非阻塞输入?
答案 0 :(得分:0)
假设您使用Windows,可能这意味着读取输出的程序不能经常读取它(它可以让它大量增加),然后当管道的总大小达到一定大小(通常为几MB)时窗户停止处理。
这是一种新情况,需要深入研究Windows管道和作业控制。在FPC 3.x TProcess中,修复了一些错误,它们是相似的(如果stderr也没有定期处理,管道处理会停止,请参阅内部命令代码)。
如果接收程序没有处理stderr,请不要使用它。
答案 1 :(得分:0)
READLN / WRITELN有效,但在读取READLN之前停止程序。
TInputPipeStream / WRITELN在不停止程序的情况下工作,因此解决了我的问题。
TInputStream / TOutputStream似乎没有合作,我不知道为什么。这是我试图初始化它们的方式还是它们应该是排他性的?