使用BOOST进程在单独的线程中读取子进程标准输出 [英] Read child process stdout in a separate thread with BOOST process

查看:166
本文介绍了使用BOOST进程在单独的线程中读取子进程标准输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个主程序,该程序使用boost进程库来生成可打印的子进程

I have a main program that uses boost process library to spawn a child process that prints

Hello World !

每5秒在其标准输出上

我想在子进程的标准输出中读取/监视子进程的标准输出,并在主程序中执行其他操作.

I would like to read/monitor the stdout of the child process in the main process when it becomes available along with performing other operations within the main program.

我已经尝试了boost asynchronous IO的示例(

I have tried out the examples for boost asynchronous IO (http://www.boost.org/doc/libs/1_66_0/doc/html/boost_process/tutorial.html) but all these seem to block the main program until the child process has exited.

我们是否需要在单独的线程中读取childs stdout?有人可以提供一个示例,在该示例中主程序可以同时执行其他操作,而不是阻止孩子的stdout吗?

Do we need to read the childs stdout in a separate thread ? Can someone please provide an example where the main program can do other things at the same time instead of blocking for stdout from th child ?

推荐答案

我已经尝试了用于增强异步IO的示例(

I have tried out the examples for boost asynchronous IO (http://www.boost.org/doc/libs/1_66_0/doc/html/boost_process/tutorial.html) but all these seem to block the main program until the child process has exited.

再看一次. 异步I下的所有示例/O 应该可以帮助您选择一种适合您的方法.

Look again. All the samples under Asynchronous I/O should help you select a method that works for you.

我们是否需要在单独的线程中读取childs stdout?有人可以提供一个示例,说明主程序可以同时执行其他操作,而不是阻止孩子的stdout吗?

Do we need to read the childs stdout in a separate thread ? Can someone please provide an example where the main program can do other things at the same time instead of blocking for stdout from th child ?

不,您不需要 .尽管您可以,并且取决于要实现的目标,但这可能是最容易的事情.

No, you don't need to. Though you can and depending on what you're trying to achieve, it might be the easiest thing to do.

您没有告诉我们您想做什么,所以让我们假设您只想打印输出:

You failed to tell us what you want to be able to do, so let's assume you just want the output printed:

在Coliru上直播 :

bp::child c("/bin/bash", std::vector<std::string> { "-c", "for a in {1..10}; do sleep 2; echo 'Hello World !'; done" });
c.wait();

那是同步的,因此您不能同时进行工作

That's synchronous, so you can't do work in the meantime

就像:

在Coliru上直播 :

#include <boost/process.hpp>
#include <boost/process/async.hpp>
#include <iostream>

namespace bp = boost::process;

int main() {
    bp::ipstream output;
    std::thread reader([&output] {
        std::string line;
        while (std::getline(output, line))
            std::cout << "Received: '" << line << "'" << std::endl;
    });

    bp::child c("/bin/bash",
        std::vector<std::string> { "-c", "for a in {1..10}; do sleep 2; echo 'Hello World ('$a')!'; done" },
        bp::std_out > output);

    while (c.running()) {
        std::this_thread::sleep_for(std::chrono::milliseconds(2793));
        std::cout << "(main thread working)" << std::endl;
    }

    std::cout << "(done)" << std::endl;
    c.wait();

    output.pipe().close();
    reader.join();
}

打印( 在Coliru上直播 ):

Received: 'Hello World (1)!'
(main thread working)
Received: 'Hello World (2)!'
(main thread working)
Received: 'Hello World (3)!'
Received: 'Hello World (4)!'
(main thread working)
Received: 'Hello World (5)!'
(main thread working)
Received: 'Hello World (6)!'
(main thread working)
Received: 'Hello World (7)!'
Received: 'Hello World (8)!'
(main thread working)
Received: 'Hello World (9)!'
(main thread working)
Received: 'Hello World (10)!'
(main thread working)
(done)

异步IO

不使用任何线程(好吧,只是主线程),就像这样:

Asynchronous IO

Using no threads (well, just the main thread), could look like:

在Coliru上直播

#include <boost/process.hpp>
#include <boost/process/async.hpp>
#include <boost/asio/high_resolution_timer.hpp>
#include <iostream>
#include <iomanip>

namespace bp = boost::process;

struct OtherWork {
    using clock = std::chrono::high_resolution_clock;

    OtherWork(boost::asio::io_context& io) : timer(io) { }

    void start() {
        timer.expires_at(clock::time_point::max());
        loop();
    }

    void stop() {
        timer.expires_at(clock::time_point::min());
    }

  private:
    void loop() {
        if (timer.expires_at() == clock::time_point::min()) {
            std::cout << "(done)" << std::endl;
            return;
        }

        timer.expires_from_now(std::chrono::milliseconds(2793));
        timer.async_wait([=](boost::system::error_code ec) {
            if (!ec) {
                std::cout << "(other work in progress)" << std::endl;
                start();
            } else {
                std::cout << "(" << ec.message() << ")" << std::endl;
            }
        });
    }

    boost::asio::high_resolution_timer timer;
};

int main() {
    boost::asio::io_context io;
    bp::async_pipe output(io);

    OtherWork mainwork{io};

    bp::child c("/bin/bash", std::vector<std::string> { "-c", "for a in {1..10}; do sleep 2; echo 'Hello World ('$a')!'; done" },
            bp::std_out > output, io, bp::on_exit([&mainwork,&output](auto...) {
                    output.close();
                    mainwork.stop();
                }));

    std::function<void()> readloop = [&,buffer=std::array<char, 32>{}]() mutable {
        output.async_read_some(bp::buffer(buffer), [&](boost::system::error_code ec, size_t transferred) {
                if (transferred) {
                    std::cout << "Received: '";
                    while (transferred && buffer[transferred-1] == '\n') // strip newline(s)
                        --transferred;
                    std::cout.write(buffer.data(), transferred);
                    std::cout << "'" << std::endl;
                }

                if (ec)
                    std::cout << "Output pipe: " << ec.message() << std::endl;
                else
                    readloop();
            });
    };

    mainwork.start();
    readloop();
    io.run();
}

打印 在Coliru上直播

Received: 'Hello World (1)!'
(other work in progress)
Received: 'Hello World (2)!'
(other work in progress)
Received: 'Hello World (3)!'
Received: 'Hello World (4)!'
(other work in progress)
Received: 'Hello World (5)!'
(other work in progress)
Received: 'Hello World (6)!'
(other work in progress)
Received: 'Hello World (7)!'
Received: 'Hello World (8)!'
(other work in progress)
Received: 'Hello World (9)!'
(other work in progress)
Received: 'Hello World (10)!'
Output pipe: End of file
Child exited with code=0(Success)
(Operation canceled)

这篇关于使用BOOST进程在单独的线程中读取子进程标准输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆