提升:如何创建一个线程,以便您可以控制其所有标准输出,标准错误?

时间:2010-11-25 16:13:05

标签: c++ multithreading boost output-buffering

我用C ++创建了一个win32控制台应用程序。我使用一些API(不是我的,我不能修改它的来源)。编写它是为了将它的一些信息写入控制台屏幕而不是每次调用它(每秒48次)所以我想将它放入某个线程并限制其输出功能,但我需要得到它当该线程尝试输出一些对我很重要的消息时通知。我在标准字符串中有消息文本。如何使用boost在C ++中做这样的事情?

3 个答案:

答案 0 :(得分:2)

这是一个疯狂的想法:

如果lib正在使用cout / cerr,您可以使用自己的实现替换这些全局变量的streambuf。它会在flush / data上检查一些线程局部变量以查看数据是否来自调用库的线程,然后将其路由到其他地方(即进入std :: string / std :: ostringstream)而不是常规的cout / cerr streambufs。 (你应该保留它。)

如果它正在使用c的stdout / stderr,我认为这样做会更难,但它仍然可行。你需要创建一些管道并来回路由。那么更多的C / unixy问题,我还不太了解...... :)

希望它有所帮助。

答案 1 :(得分:1)

我无法想到在Boost中实现你想要的东西,因为问题已经描述过了。

但是,这种API行为非常令人困惑。将大量输出吐出到控制台有点反社会。您使用的是API库的Debug版本吗?您确定无法配置API以便将此数据输出到其他流,以便您可以过滤它而不捕获整个标准输出吗?有没有办法减少输出量,这样你才能看到你关心的重要事件?

如果你真的需要捕获标准输出并对某些感兴趣的字符串(事件)采取行动,那么Win32提供了这样做的方法,但我真的很想看看是否可以修改这个输出来满足你的需求在诉诸于此之前。

答案 2 :(得分:1)

Boost中不存在该功能。但是,您可以使用_dup2替换标准输出描述符:

#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <io.h>
#include <iostream>
#include <windows.h>

int main()
{
    HANDLE h = CreateFile(TEXT("test.txt"), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (0 == SetStdHandle(STD_OUTPUT_HANDLE, h)) {
        std::fprintf(stderr, "`SetStdHandle` failed with error %d\n", (int)GetLastError());
        return EXIT_FAILURE;
    }

    int h_desc = _open_osfhandle((long)h, 0);
    _dup2(h_desc, STDOUT_FILENO);

    std::printf("test\r\n"); // This actually writes to `h`.
    std::fflush(stdout);

    std::cout << "another test" << std::endl; // Also writes to `h`

    CloseHandle(h);
    return EXIT_SUCCESS;
}

基本上,这个技巧的作用是允许您将对stdoutstd::coutGetStdHandle(STD_OUTPUT_HANDLE)的所有写入重定向到您选择的可写句柄(h)。当然,您可以使用CreatePipe创建可写句柄(h)并从另一个线程中的可读端读取。

编辑:如果您正在寻找跨平台解决方案,请注意,在兼容POSIX的系统上,此技巧更加简单,因为dup2unistd.h中的标准功能和“可写句柄”已经是描述符。