防止boost :: asio :: io_context在空轮询中停止 阻止io_context耗尽工作

问题描述

代码称为发布的句柄

    boost::asio::io_context ioc;
    boost::asio::post(ioc,[]{ std::cout << "lol" << std::endl; });
    ioc.poll();

而事实并非如此:

    boost::asio::io_context ioc;
    ioc.poll(); // empty,set internal state to stopped_
    boost::asio::post(ioc,[]{ std::cout << "lol" << std::endl; });
    ioc.poll(); // doesn't work as stopped() Now returns true

Live example

是设计使然吗?如果是,为什么?我可以通过某种方式配置io_context来更改此行为吗?

解决方法

此文档(不是最佳位置,应在poll文档中提及):

io_context::restart - develop

io_context::restart

重新启动io_context,以准备后续的run()调用。

void restart();

在先前调用run()run_one()poll()poll_one()函数的第二次或更多次调用之前,必须先调用此函数由于io_context被停止或没有工作而返回。调用restart()之后,io_context对象的stopped()函数将返回false

在未完成对run()run_one()poll()poll_one()函数的调用时,不得调用此函数。

因此,基本上,您需要添加restart才能使其正常工作。

https://wandbox.org/permlink/aXzz5GCAIMIvStnl

这是an extra clue原因。

,

io_service / io_context旨在在它们用尽时停止工作。

io_serviceio_context的文档包含:

阻止io_context耗尽工作

某些应用程序可能需要在没有更多工作要做时阻止io_context对象的run()调用返回。例如,io_context可能在后台线程中运行,该后台线程在应用程序的异步操作之前启动。可以通过创建类型为boost :: asio :: executor_work_guard

的对象来保持run()调用的运行。
boost::asio::io_context io_context;
boost::asio::executor_work_guard<boost::asio::io_context::executor_type>
  = boost::asio::make_work_guard(io_context);
...

要实现关闭,应用程序将需要调用io_context对象的stop()成员函数。这将导致io_context run()调用尽快返回,放弃未完成的操作,并且不允许分派就绪的处理程序。

或者,如果应用程序要求允许所有操作和处理程序正常完成,则可以显式重置工作对象。

boost::asio::io_context io_context;
boost::asio::executor_work_guard<boost::asio::io_context::executor_type>
  = boost::asio::make_work_guard(io_context);
...
work.reset(); // Allow run() to exit.

请注意,“老式”的Asio接口使用了一个不太通用的io_service::work对象:

io_service ios;
io_service::work work(ios); // old interface!

这将需要您做一些额外的工作才能重置它:

asio::io_service ios;
std::optional<asio::io_service::work> work(ios);
// ...
work.reset();

重新启动

最后,当上下文 did 用尽时,您将必须restart()进行重用:

enter image description here

理性

我认为设计的理由来自没有任何图书馆的图书馆 关于如何在调度和线程方面运行服务的意见, 结合保证io_context / io_service必须是 线程安全²。参见docs for background


¹旁注:同样,thread_pool(就像execution_context一样是io_context)不是为了重复使用而设计的(例如参见Boost asio thread_pool join does not wait for tasks to be finished)>

²当然,除了对象生命期(构造/破坏)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...