我正在使用CreateProcess
从Win32生成一个进程,将hStdOutput
的{{1}}和hStdError
属性设置为使用STARTUPINFO
创建的管道句柄。我有两个线程读取管道,等待数据可用(或完成的过程,此时它检查在终止线程之前没有剩余数据)。
随着数据变得可用,我将输出写入有效的大文本框。
正在发生的事情是输出被缓冲,因此缓慢运行的进程只会获取文本框中抛出的数据块,但不会“正常”。
我不确定它是否正在进行缓冲管道,或者与重定向有关。
有没有办法将管道设置为无缓冲,或者以尽快发送stdout的方式启动进程?
我正在使用测试应用程序进行测试,该应用程序会间隔一秒打印行
CreatePipe
答案 0 :(得分:4)
缓冲可能在C运行时(printf等),你可以做的很少(IIRC它会进行isatty()检查以确定缓冲策略)
答案 1 :(得分:0)
有SetNamedPipeHandleState,但它只控制远程管道的缓冲,而不是两端都在同一台计算机上。
答案 2 :(得分:0)
在我看来,如果将hStdOutput
hStdError
STARTUPINFO
而非设置为使用{{1}创建的管道句柄,则可以解决问题},而不是你创建一个命名管道(CreatePipe
功能完全像你之前使用的CallNamedPipe
= bInheritHandle
使用SECURITY_ATTRIBUTES,请参阅http://msdn.microsoft.com/en-us/library/aa365782.aspx)然后使用TRUE
标志在CreateFile
方面按名称打开。就像您可以在MSDN上阅读(http://msdn.microsoft.com/en-us/library/aa365592.aspx):
管道客户端可以使用CreateFile 通过指定启用重叠模式 FILE_FLAG_OVERLAPPED或启用 通过指定直写模式 FILE_FLAG_WRITE_THROUGH。
因此,只需使用FILE_FLAG_WRITE_THROUGH
标志重新打开CreateFile
管道,并将句柄/句柄设置为FILE_FLAG_WRITE_THROUGH
的{{1}}和hStdOutput
。
答案 3 :(得分:0)
在我的情况下,缓冲是在客户端的输出中(如@Anders 所写),它使用普通的 printf
。也许这也取决于 C 运行时(Visual Studio 2019)的实现,也许运行时检测到“不是控制台”并启用缓冲。
所以我通过这个调用禁用了缓冲
setvbuf(stdout, (char*)NULL, _IONBF, 0);
在我的客户端中,现在我立即在服务器的管道中获得输出。
只是为了完整性:这是我在服务器中读取管道的方式
HANDLE in;
CreatePipe(&in, &startup.hStdOutput, &sa, 0); // Pipe for stdout of the child
...
char buffer[16384];
DWORD read, total;
while (PeekNamedPipe(in, NULL, 0, &read, &total, NULL))
{
if (total == 0)
{
if (WaitForSingleObject(info.hProcess, 0) == WAIT_OBJECT_0)
{
if (PeekNamedPipe(in, NULL, 0, &read, &total, NULL) && total == 0)
break;
continue;
}
Sleep(10);
continue;
}
if (total > sizeof(buffer))
total = sizeof(buffer);
ReadFile(in, buffer, total, &read, NULL);
...
}