代码之家  ›  专栏  ›  技术社区  ›  Dave Brotherstone

禁用重定向STDUT管道(Win32 API,C++)缓冲

  •  13
  • Dave Brotherstone  · 技术社区  · 14 年前

    CreateProcess ,设置 hStdOutput hStdError 的属性 STARTUPINFO 创建管道控制柄的步骤 CreatePipe . 我有两个线程在读取管道,等待数据可用(或者进程完成,在终止线程之前检查是否没有数据)。
    当数据可用时,我将输出有效地写入一个大文本框。

    所发生的是输出被缓冲,所以一个运行缓慢的进程只会得到文本框中抛出的数据块,而不是“它发生时”。

    有没有办法将管道设置为无缓冲区,或者以尽快发送stdout的方式启动进程?

    我正在用一个测试应用程序测试,它每隔一秒钟打印一行

    Here is line one
    (waits one second)
    Here is line two
    (waits one second)
    ... etc
    
    3 回复  |  直到 10 年前
        1
  •  4
  •   Anders    14 年前

        2
  •  1
  •   Ben Voigt    14 年前
        3
  •  0
  •   Oleg    14 年前

    在我看来,如果你定下目标,你就能解决这个问题 hStdOutput hStdError STARTUPINFO 创建管道控制柄的步骤 CreatePipe CallNamedPipe 功能与您在使用SECURITY\u属性之前使用的if完全相同 bInheritHandle = TRUE ,请参见 http://msdn.microsoft.com/en-us/library/aa365782.aspx CreateFile 使用 FILE_FLAG_WRITE_THROUGH 旗帜。就像你能在MSDN上看到一样( http://msdn.microsoft.com/en-us/library/aa365592.aspx

    管道客户端可以使用CreateFile 通过指定 文件\u标志\u重叠或启用 通过指定

    创建文件 使用 标记并将handle/handles设置为 HST输出 HSTD错误 属于 STARTUPINFO公司 .

        4
  •  0
  •   some guy    3 年前

    printf . 也许这还取决于C运行时(VisualStudio2019)的实现,也许运行时检测到“不是控制台”并启用缓冲。

    所以我用这个调用禁用了缓冲 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);
    
        ...
    }