C++ Boost asio-停止io_服务
我正在使用boost::asio进行一些非常基本的UDP数据包收集。io_服务对象在工作线程中实例化,并从该线程内部调用io_服务.run()。我的问题是在收集完数据包后让io_service.run()返回 我不清楚在停止我的工作线程时,可以从其他线程调用io_服务的哪些方法。我有一个对io_服务对象的引用,我从另一个线程调用:C++ Boost asio-停止io_服务,c++,boost,boost-asio,C++,Boost,Boost Asio,我正在使用boost::asio进行一些非常基本的UDP数据包收集。io_服务对象在工作线程中实例化,并从该线程内部调用io_服务.run()。我的问题是在收集完数据包后让io_service.run()返回 我不清楚在停止我的工作线程时,可以从其他线程调用io_服务的哪些方法。我有一个对io_服务对象的引用,我从另一个线程调用: ios.dispatch( boost::bind( &udp_server::handle_kill, this ) ); 在我的udp_服务器类中,该函
ios.dispatch( boost::bind( &udp_server::handle_kill, this ) );
在我的udp_服务器类中,该函数的处理程序从单个boost::asio::ip::udp::socket和单个boost::asio::deadline_计时器对象中取消挂起的工作。两者都有挂起的异步工作要做。此时我调用ios.stop():
在没有挂起的工作的情况下,我希望此时可以返回对ios.run()的调用,但这不会发生
那么为什么它不回来呢?最可能的解释是,我不应该从另一个线程调用io_service::dispatch()。但是dispatch()方法似乎就是为了实现这一点而构建的——在io_service::run()工作的线程中调度函数调用。它似乎就是这样做的
这就给我留下了几个相关的问题:
socket::udp::close()似乎不会取消挂起的async_receive_from()任务,因此调用它而不是socket::udp::cancel()似乎会将线程留在io_service::run()中的某个位置。从另一个线程调用
io_service::stop
是安全的,这在文档中
线程安全
不同对象:安全
共享对象:安全,具有
调用reset()时发生异常
有未完成的run(),run_one(),
poll()或poll_one()调用会导致
未定义的行为
正如对您问题的评论所指出的,您确实需要将其归结为一个可重复的示例。是否有理由将
handle\u kill
发送到io\u服务
?在该线程中调用handle\u kill()
应该是安全的。如果这样做,它是否仍然挂在run()
?这是一个工作线程-除了读取数据包之外,它什么都不做。终止线程的动力来自另一个线程中的GUI。无论我使用哪种方法,都必须有一种线程安全的方式来与io_service::run()线程通信。在我看来,io_service::dispatch()就是为了满足这种需要而构建的。handle_kill()似乎是在正确的线程中调用的。您应该能够从任何线程停止io_服务
,而不管它是否是该特定io_服务
的工作线程。另外,dispatch()
和post()
是相同的,不同的是如果可能,dispatch()
可以立即内联调用函数(如果dispatch
是从io\u服务
线程调用的)。因此,如果您知道您的dispatch()
调用永远不会在io\u服务
线程上,那么它与post()
相同。但这并不能解决你的问题。你能给出一个10-15行的代码样本来重现这个问题吗?我正在准备一个简短的例子来说明这一点。同时,我发现从另一个线程调用ios::stop()实际上会导致ios:run()以我想要的方式退出。我曾经(现在仍然)不愿意对一个没有显式调用线程安全行为保证的方法进行这样的调用,但它似乎确实有效。为什么我通过dispatch()进行的间接调用不起作用的问题还有待复制和理解。@MarkNelson,请接受提供的答案,如果它足够的话。我阅读了关于线程安全的说明,我不得不承认我对文档中“共享对象”的含义有点一无所知。这似乎相当笼统,但回想起来,我认为你是对的,它描述得很好。这些知识并没有具体回答我的问题,但因为它为解决我的bug扫清了道路,所以它是次好的选择。谢谢@马克:如果你满意的话,欢迎接受我对你问题的回答。您可能想为您的bug发布一个新问题。
void udp_server::handle_kill()
{
m_socket.cancel();
m_timer.cancel();
m_ios.stop();
}