【问题标题】:Stopping the io_service after every thread is finished每个线程完成后停止 io_service
【发布时间】:2018-10-09 03:02:04
【问题描述】:

我想让程序等到它完成所有正在运行的线程,这与ioService.stop(); 不同,后者无需等待即可停止ioService。我尝试了以下代码,它工作正常,但停止 ioService 而不等待线程完成。

#include <iostream>
#include <boost/asio/io_service.hpp>
#include <boost/bind.hpp>
#include <boost/thread/thread.hpp>


void myTask (std::string &str);

int main(int argc, char **argv){

    uint16_t total_threads = 4;

    /*
     * Create an asio::io_service and a thread_group
     */
    boost::asio::io_service ioService;
    boost::thread_group threadpool;    

    /*
     * This will start the ioService processing loop. 
     */     
    boost::asio::io_service::work work(ioService);

    /*
     * This will add threads to the thread pool.
     */
    for (std::size_t i = 0; i < total_threads; ++i)
        threadpool.create_thread(
                boost::bind(&boost::asio::io_service::run, &ioService));    

    /*
     * This will assign tasks to the thread pool.
     */
    std::string str = "Hello world";
    ioService.post(boost::bind(myTask, std::ref(str) ));



    ioService.stop();

    /*
     * thread pool are finished with
     * their assigned tasks and 'join' them.
     */
    threadpool.join_all();

    return 0;

}


void myTask (std::string &str){
    std::cout << str << std::endl;
}

编译:-lboost_serialization -lboost_thread -lboost_system

【问题讨论】:

  • 如果您甚至没有得到要编译的东西,停止服务不是您的问题,因此您可能应该重新考虑您的问题。另外,提取minimal reproducible example
  • @UlrichEckhardt 怎么不是Minimal, Complete, and Verifiable example?我已经给出了每个人都可以运行并验证错误和其他详细信息的最少代码。
  • 可以打包成一个文件吗?你能删除导致错误的行后面的行吗?
  • @UlrichEckhardt 我已经更新了我的问题。谢谢。

标签: c++ boost boost-asio boost-thread


【解决方案1】:

您的问题是您正在创建 work 作为堆栈上的变量。 work 告诉 io_service 还有工作要做。来自手册:

析构函数通知 io_service 工作完成。

由于工作是在堆栈的 main 中创建的,因此它的生命周期比您希望的要长。在主退出之前它不会被破坏。而是在堆上创建它,这样您就可以显式地销毁它。将其更改为:

using namespace boost::asio;
boost::scoped_ptr<io_service::work> work(new io_service::work(ioService));

然后,稍后,当您想告诉 io_service 在完成所有未完成的工作后停止时,不要停止 io_service 而是销毁“工作”,然后等待线程完成。

work.reset();
threadpool.join_all();

这将调用~work(),它将从 io_service 中删除工作对象。这反过来会导致io_service::run 在最后一个挂起的操作完成后退出。

还有一些注意事项:

  • 我会避免为变量提供与其类相同的名称。我不会写io_service::work work(io_service); 这太混乱了。我会写类似io_service::work some_work(io_service);
  • 小心io_service.post(... std::ref(str)); 您正在传递对 io_service 发布操作的引用。变量 str 必须存在足够长的时间才能完成任务。我相信这只是为了举例。在现实世界的应用程序中,要确保传递给工作对象的参数不会过早地被破坏是非常困难的。我经常使用shared_ptr&lt;&gt;,或者在不可能的情况下,我有时会使用 boost::atomic 来计算未完成的 io_service 操作的数量

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-29
    • 2021-12-25
    • 2013-08-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多