如何在停止 io_service 之前等待所有挂起的完成处理程序被执行?

bob*_*eff 5 c++ multithreading boost boost-asio

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

seh*_*ehe 4

只需重置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();
}
Run Code Online (Sandbox Code Playgroud)

1 秒后完成后台线程。

  • @bobeff,“_也许你的意思是使用动态分配的工作对象来删除_”是的,这是常见的模式。您也可以使用“boost::optional&lt;io_service::work&gt;”。 (3认同)