Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/125.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 等待增压asio';在io_服务之后,s的未来将永存。停止()_C++_Multithreading_C++11_Boost_Boost Asio - Fatal编程技术网

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::cout
io\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()使用了
,并且提供的持续时间或时间略大于
截止时间计时器
的到期时间,这样就大大减少了以后多次等待的机会。