【问题标题】:asio::io_service is ending immediately with workasio::io_service 立即以工作结束
【发布时间】:2020-08-09 07:44:51
【问题描述】:

我正在尝试学习 io_service 并使用共享指针。我希望代码可以无限工作,直到我调用 stop 方法或类似的东西。不幸的是,在屏幕上看到 workHandler 的输出后,程序关闭了。谁能解释为什么会这样?

#include <boost/asio.hpp>
#include <iostream>
#include <atomic>
#include <memory>
#include <thread>
#include <vector>

class Service : public std::enable_shared_from_this<Service> {
    std::shared_ptr<boost::asio::io_service> _service;
    std::shared_ptr<boost::asio::io_service::work> _work;
    std::vector<std::thread> _threads;
    std::atomic<bool> _started{false};

public:
    Service() 
    : _service(std::make_shared<boost::asio::io_service>()),
    _work(std::make_shared<boost::asio::io_service::work>(*_service))
    {}

    void start() { 
        auto self(this->shared_from_this());
        auto startHandler = [this, self]() {
            std::cout << "StartHandler\n";
            while(!_started) _service->run();
        };

        _threads.emplace_back(std::thread(startHandler));
    }

    std::shared_ptr<boost::asio::io_service>& get() { return _service; }
};

class Worker : public std::enable_shared_from_this<Worker> {
    std::shared_ptr<Service> _service;
    std::shared_ptr<boost::asio::io_service> _io_service;

public:
    Worker(const std::shared_ptr<Service>& service)
    : _service(service),
    _io_service(_service->get())
    {}

    void work() {
        auto self(this->shared_from_this());
        auto workHandler = [this, self]() {
            std::cout << "WorkHandler\n";
        };

        _io_service->post(workHandler);
    }
};

int main() {
    auto ser = std::make_shared<Service>();
    ser->start();
    auto worker = std::make_shared<Worker>(ser);
    worker->work();
}

【问题讨论】:

  • 我已经调试了代码,不幸的是我不知道它为什么会退出。据我了解,io_service 应该始终感谢 io_service::work 对象。在这里它在 workHandler 之后结束,所以这就是我提出问题的原因。
  • 代码执行您编写的操作。您创建对象,然后它们在范围结束时被销毁。为什么你认为它应该在退出之前停止?你从不加入的 std::thread 也会通过及时调用 std::terminate 来提供帮助。
  • 那么捕获的 shared_from_this 应该让它保持活力,@rustyx,这可能就是问题的重点。

标签: c++ multithreading c++11 c++14 boost-asio


【解决方案1】:

您遇到了未定义的行为。

您的处理程序可以捕获指向服务/工作对象的共享指针。但是没有什么能阻止main 退出,这将运行退出处理程序并拆除全球图书馆基础设施。这不是你想要的。

问题是由过度使用共享指针引起的。共享指针仅适用于共享所有权。在您的大部分代码中,没有共享所有权(main 拥有服务!)。简化:

Live On Coliru

#include <boost/asio.hpp>
#include <boost/optional.hpp>
#include <iostream>
#include <memory>
#include <thread>
#include <list>

namespace ba = boost::asio;

class Service {
    ba::io_service _service;
    boost::optional<ba::io_service::work> _work {_service};
    std::list<std::thread> _threads;

public:
    ~Service() {
        _work.reset(); // allow service to complete
        for (auto& thread : _threads)
            if (thread.joinable())
                thread.join();
    }

    void start() { 
        _threads.emplace_back([this] {
            _service.run();
        });
    }

    ba::io_service& get() { return _service; } 
};

class Worker : public std::enable_shared_from_this<Worker> {
    ba::io_service& _io;

public:
    Worker(Service& service) : _io(service.get()) {}

    void work() {
        auto self(shared_from_this());
        auto workHandler = [self]() {
            std::cout << "WorkHandler " << std::endl;
        };

        _io.post(workHandler);
    }
};

int main() {
    Service ser;
    ser.start();

    std::make_shared<Worker>(ser)->work();
}

打印

WorkHandler

但最重要的是:不调用 UB 并通过加入线程干净地退出。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2012-05-18
  • 1970-01-01
  • 2019-06-16
  • 2014-10-02
  • 1970-01-01
  • 2015-11-10
  • 1970-01-01
  • 2017-09-17
相关资源
最近更新 更多