C++ 等待增压asio';在io_服务之后,s的未来将永存。停止()
我尝试等待一个C++ 等待增压asio';在io_服务之后,s的未来将永存。停止(),c++,multithreading,c++11,boost,boost-asio,C++,Multithreading,C++11,Boost,Boost Asio,我尝试等待一个std::future对象,该对象是从任何boost::asio::async\uuu函数返回的(使用use\u future)。例如: auto endpoint_future = resolver.async_resolve(query, boost::asio::use_future); endpoint_future.wait(); // lasts forever after io_service.stop(); 这是在一个线程中完成的。 我还有另一个线程,在调用asy
std::future
对象,该对象是从任何boost::asio::async\uuu
函数返回的(使用use\u future
)。例如:
auto endpoint_future = resolver.async_resolve(query, boost::asio::use_future);
endpoint_future.wait(); // lasts forever after io_service.stop();
这是在一个线程中完成的。
我还有另一个线程,在调用async\u resolve
之前启动:
runner_ = std::thread([this]() {
boost::asio::io_service::work work(io_service_);
io_service_.run();
});
一切都很好,但后来我还添加了一个boost::asio::deadline\u计时器
,以停止使用io\u服务的任何工作
:
void deadlineTimeout() {
deadline_.cancel();
io_service_.stop();
// closing socket here does not work too
}
但是,在
deadlineTimeout()
中,当截止日期达到其超时并且它执行io\u service\u.stop()
时,未来不会被释放,因此endpointer\u future.wait()
仍会阻塞。在这种情况下,我怎样才能停止对未来的等待呢?我自己刚刚找到了一个解决方案:我们不需要停止io\u服务,而是reset()
它,在此之前我们需要关闭套接字,因此正确的超时回调将是:
void deadlineTimeout() {
deadline_.cancel();
socket_.close(); // socket_ is a socket on io_service_
io_service_.reset();
}
此更改后,所有未来都将被释放。使工作对截止时间超时可见,并允许截止时间超时删除它
boost::scoped_ptr<boost::asio::io_service::work work;
然后像这样关闭:
void deadlineTimeout() {
deadline_.cancel();
socket_.close(); // socket_ is a socket on io_service_
work.reset();
// The io_service::run() will exit when there are no active requests
// (i.e. no sockeet, no deadline, and no work)
// so you do not need to call: io_service_.stop();
}
调用io\u sevice.stop()
将导致run()
和run\u one()
的所有调用尽快返回。从处理程序中调用时,调用方将从run()
返回,而不调用任何其他处理程序。在您的情况下,async_resolve
的完成处理程序将设置与endpoint_future
关联的promise
;但是,通过停止io_服务
,将不会调用完成处理程序。考虑一下:
cancel()
与未来
关联的I/O对象,然后继续运行io\U服务
直到完成,以便设置承诺
的值
- 销毁所有I/O对象,然后销毁
io\U服务
,以便删除处理程序,并由未来
- 循环对未来执行定时等待,如果未来已准备就绪或
io\u服务已停止,则退出循环。例如,以下函数返回一个带有未来值的boost::optional
,或者如果不设置未来值,则返回boost::none
模板
boost::可选的get(
boost::asio::io_服务和io_服务,
标准:未来与未来)
{
对于(;;)
{
//如果未来已经准备好,请获取价值。
if(future.wait_for(std::chrono::seconds(1))==std::future_status::ready)
{
返回{future.get()};
}
//否则,如果未来永远不会被设定,则返回none。
if(io_service.stopped())
{
返回{boost::none};
}
}
}
...
if(自动端点迭代器=get(io_服务,端点_未来))
{
//使用*endpoint\u迭代器。。。
}
下面是一个示例,说明如何在停止io\u服务时安全地等待未来:
void deadlineTimeout() {
deadline_.cancel();
io_service_.stop();
// closing socket here does not work too
}
#包括
#包括
#包括
#包括
#包括
#包括
模板
boost::可选的get(
boost::asio::io_服务和io_服务,
标准:未来与未来)
{
对于(;;)
{
//如果未来已经准备好,请获取价值。
if(future.wait_for(std::chrono::seconds(1))==std::future_status::ready)
{
返回{future.get()};
}
//否则,如果未来永远不会被设定,则返回none。
if(io_service.stopped())
{
std::coutio\u service::stop()
只需设置一个标志,要求服务“尽快”停止。只要套接字上有未完成的读取,服务就无法停止,因此socket\u.close()
是答案的重要部分。你错了。关闭套接字并调用io\u service.stop()after不起作用。这里重要的是调用reset()而不是stop()。对仍在运行的io_服务调用reset()是错误的。您应该完全关闭它。如果您计划在服务停止后重新使用该服务,则可以使用reset。您还需要在服务停止之前删除工作。(Reset是通过蛮力(讨厌的))文档严格禁止调用io\u服务上的Reset()
,而对poll()
、poll\u one()
、run()
或run\u one()
的调用尚未完成
可能会产生不良影响。取消的异步解析
操作的内部完成处理程序可能永远不会被调用,从而导致std::promise
从未设置其值。使用wait\u for
等待并检查某些内容是我希望避免的无用开销。我考虑过这一点s的解决方案,但我试图找到更有效的方法,无需手动操作即可释放我等待的所有未来。这是否可以正确执行(如果错误,无需重置
)?@VictorPolevoy据我所知,只有3种行为定义良好的选项:运行处理程序;销毁处理程序;或定期等待处理程序。在一个可能永远不会完成的异步操作上无限期地同步阻止似乎很尴尬。如果wait_for()
或wait_until()使用了
,并且提供的持续时间或时间略大于
截止时间计时器
的到期时间,这样就大大减少了以后多次等待的机会。