从并发析构函数中停止 boost::asio::io_service::run()

Mar*_*tin 6 c++ boost boost-asio

谁能解释一下为什么这个程序没有终止(见评论)?

#include <boost/asio/io_service.hpp>
#include <boost/asio.hpp>
#include <memory>
#include <cstdio>
#include <iostream>
#include <future>

class Service {
public:
    ~Service() {
        std::cout << "Destroying...\n";
        io_service.post([this]() {
            std::cout << "clean and stop\n"; // does not get called
            // do some cleanup
            // ...
            io_service.stop();
            std::cout << "Bye!\n";
        });
        std::cout << "...destroyed\n"; // last printed line, blocks
    }

    void operator()() {
        io_service.run();
        std::cout << "run completed\n";
    }

private:
    boost::asio::io_service io_service;
    boost::asio::io_service::work work{io_service};
};

struct Test {
    void start() {
        f = std::async(std::launch::async, [this]() { service(); std::cout << "exiting thread\n";});
    }
    std::future<void> f;
    Service service;
};

int main(int argc, char* argv[]) {
    {
        Test test;
        test.start();

        std::string exit;
        std::cin >> exit;
    }

    std::cout << "exiting program\n"; // never printed
}
Run Code Online (Sandbox Code Playgroud)

axa*_*lis 2

请参阅此处:在抛出 io_service::run() 后,boost::asio 挂在解析器服务析构函数中

我认为这里的技巧是work在调用之前销毁工人(成员)io_service.stop()。即在这种情况下,work可以是unique_ptr, 并reset()在停止服务之前显式调用。

编辑:上面的内容不久前对我的情况有所帮助,其中ioservice::stop没有停止并正在等待一些从未发生的调度事件。

然而,我重现了您在我的机器上遇到的问题,这似乎是内部的竞争条件,以及破坏代码( )ioservice之间的竞争。特别是,如果在通知唤醒另一个线程之前触发,则代码会从队列中删除该操作(并“销毁”它而不是调用它),因此 lambda 永远不会被调用。ioservice::post()ioserviceshutdown_serviceshutdown_service()post()shutdown_service()

现在在我看来,您需要io_service.stop()直接在析构函数中调用,而不是通过推迟,post()因为由于竞争,这显然在这里不起作用。