【问题标题】:How to wait for all pending completion handlers to be executed before stopping io_service?如何在停止 io_service 之前等待所有待处理的完成处理程序执行?
【发布时间】:2016-10-14 15:52:11
【问题描述】:

我正在使用boost::asio 编写服务器。我有多个线程,每个线程都拥有它自己的 io_service 对象。当没有要执行的完成处理程序时,我使用io_service::work 对象来保持io_service 运行。在某个时刻,我正在调用io_service 对象的stop 方法来完成调用io_serice::run 的线程。但是在某些情况下,当我调用stop 时,我已经在io_service 中发布了尚未完成的对象竞争处理程序。调用stop 会阻止发布的竞争处理程序执行,但这对我来说是不可接受的,因为我需要在停止线程之前完成所有待处理的工作。如何在调用io_servicestop 方法之前等待所有待处理的完成处理程序首先执行?

【问题讨论】:

    标签: c++ multithreading boost boost-asio


    【解决方案1】:

    只需重置work

    所有待处理的工作完成后,任何io_service::run() 都会返回。

    常见的模式是使用optional<work>,这样你就可以清除它。如果这是经常发生的事情,您可以通过将其包装在启用 RAII 的类中来减少一些心理开销:

    Live On Coliru

    #include <boost/asio.hpp>
    #include <boost/optional.hpp>
    
    struct work {
        using io_service = boost::asio::io_service;
        work(io_service& svc) : _work(io_service::work(svc)) 
        { }
    
        void release() {
            _work.reset();
        }
    
        void enlist(io_service& svc) {
            _work.emplace(io_service::work(svc));
        }
    
      private:
        boost::optional<io_service::work> _work;
    };
    
    #include <thread>
    #include <iostream>
    using namespace std::chrono_literals;
    
    int main() {
        boost::asio::io_service svc;
        work lock(svc);
    
        std::thread background([&] { svc.run(); });
    
        std::this_thread::sleep_for(1s);
    
        std::cout << "releasing work";
        lock.release();
    
        background.join();
    }
    

    1秒后结束后台线程。

    【讨论】:

    • 如何重置work?我没有看到work 类的reset 方法,也没有看到io_service 类。也许您的意思是在我想停止时使用动态分配的work 对象delete(或重置std::unique_ptr&lt;io_service::work&gt;)?
    • @bobeff, "也许你的意思是使用动态分配的工作对象来删除" 是的,这是常见的模式。你也可以使用boost::optional&lt;io_service::work&gt;
    • @bobeff 是的。我在答案中添加了一些示例代码。
    猜你喜欢
    • 2018-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-27
    • 2016-02-08
    • 2014-04-21
    相关资源
    最近更新 更多