停止 boost::asio 操作的规范方法

Posted

技术标签:

【中文标题】停止 boost::asio 操作的规范方法【英文标题】:Canonical way to stop boost::asio operations 【发布时间】:2012-10-04 13:03:30 【问题描述】:

我有一个boost::asio::io_service 在执行某些操作的线程中运行:

struct clicker

    clicker(boost::asio::io_service& io) : timer_(io)  wait_for_timer(); 

    void stop()  timer_.cancel(); 

    void wait_for_timer()
    
        timer_.expires_from_now(std::chrono::milliseconds(500));
        timer_.async_wait(std::bind(&clicker::wait_completed, this, _1));
    

    void wait_completed(const boost::system::error_code& err)
    
        if (!err) 
            std::cout << "Click" << std::endl;
            wait_for_timer();
        
    

    boost::asio::steady_timer timer_;
;

int main()

    boost::asio::io_service io;
    clicker cl(io);

    std::thread io_thread(&boost::asio::io_service::run, &io);

    while (true)  // the run loop
        // gather input
        if (user_clicked_stop_button())  cl.stop(); break; 
    

    io_thread.join();

现在调用stop() 应该取消等待计时器并触发wait_completed() 并出现错误。然而,我们这里有一个竞争条件:有时,stop() 将在 wait_for_timer() 运行时和 async_wait 被安排之前被调用。然后,代码将无限期地运行。

处理这种情况的推荐方法是什么?在 wait_completed 中测试的 clicker 中的布尔标志?互斥体?

更新:

这只是一个简化的例子,在实际代码中我有几个操作在io_service 中运行,所以这里不能调用io_service::stop()

【问题讨论】:

【参考方案1】:

将操作发布到 io_service 线程:

void stop() 
 
  timer_.get_io_service().post([=]  timer_.cancel(); ); 
 

(如果您的编译器不兼容 c++11,请使用 bind 创建 lambda。)

【讨论】:

【参考方案2】:

我想你想调用io.stop() 来停止 io_service 对象。

【讨论】:

这只是一个简化的例子。我希望其他操作继续进行。 啊,我错过了。在这种情况下,将取消操作发布到 io_service。 io.post(boost::bind(&clicker::stop, cl));

以上是关于停止 boost::asio 操作的规范方法的主要内容,如果未能解决你的问题,请参考以下文章

安全地完成读取操作 (Boost.Asio)

Boost::asio::async_read 不会在条件下停止

boost::asio::thread_pool - 如何在工作完成前取消工人?

boost::asio 错误“I/O 操作已中止...”

防止 boost::asio::io_context 在空投票调用时停止

Boost::Asio入门剖析