取消boost::asio处理程序的处理程序何时开始运行?
取消异步连接、发送和接收的boost文档将立即完成,取消操作的处理程序将被传递boost::asio::error::operation\u aborted error 我想知道在其他(未取消和新安排的)完成处理程序运行之前,取消的处理程序是否运行(并查看操作\u中止错误) 以下是我关注的时间线: acceptHandler和readHandler在同一事件循环和同一线程上运行取消boost::asio处理程序的处理程序何时开始运行?,boost,boost-asio,Boost,Boost Asio,取消异步连接、发送和接收的boost文档将立即完成,取消操作的处理程序将被传递boost::asio::error::operation\u aborted error 我想知道在其他(未取消和新安排的)完成处理程序运行之前,取消的处理程序是否运行(并查看操作\u中止错误) 以下是我关注的时间线: acceptHandler和readHandler在同一事件循环和同一线程上运行 时间t0-readHandler正在oldConnectionSocket上运行 时间t1-acceptHandle
- 时间t0-readHandler正在oldConnectionSocket上运行
- 时间t1-acceptHandler运行
- 时间t2-acceptHandler调用oldConnectionSocket.cancel
- 时间t3-acceptHandler关闭oldConnectionSocket
- 时间t4-acceptHandler调用newConnectionSocket.async\u read(…readHandler…)
- 调用时间t5-readHandler(从哪个上下文?)
在t5时,在调用readHandler之前,是否有可能在newConnectionSocket上下文中调用readHandler,然后在oldConnectionSocket上下文中调用该readHandler,操作被中止错误?已取消的操作将立即发布其处理程序以进行延迟调用。但是,不保证处理程序的调用顺序。因此,
io_服务
可以选择按任意顺序调用readHandler。目前,只有a指定在某些条件下的保证顺序
在完成处理程序中,如果目标是知道哪个I/O对象与操作关联,那么考虑构造完成处理程序,使其具有对I/O对象的显式句柄。这通常通过使用以下任何一项来实现:
- 自定义函子
或std::bind()
boost::bind()
- 一个C++11lambda
boost::enable_shared_from_this
继承时,它提供了一个shared_from_this()
成员函数,该函数将有效的shared_ptr
实例返回到this
。shared\u ptr
的副本传递给完成处理程序,例如lambdas中的捕获列表,或者作为实例句柄传递给boost::bind()
。这允许处理程序知道在其上执行操作的I/O对象,并导致I/O对象的生存期至少延长到与处理程序相同的长度。有关使用此方法的示例,请参见Boost.Asio教程
class-tcp\u连接
:public boost::从\u启用\u共享\u
{
公众:
// ...
void start()
{
boost::asio::异步写入(套接字写入。。。,
boost::bind(&tcp_connection::handle_write,shared_from_this(),
boost::asio::占位符::错误,
boost::asio::占位符::字节(已传输);
}
无效句柄(
常量boost::system::error\u代码和错误,
std::大小(传输的字节数)
{
//I/O对象是这个->套接字。
}
tcp::socket-socket;
};
另一方面,如果目标是确定一个处理程序是否在另一个处理程序之前执行,则:
- 应用程序将需要显式管理状态
- 试图管理多个依赖的调用链可能会引入不必要的复杂性,并且通常表明需要重新检查设计
- 自定义处理程序可用于确定处理程序执行顺序的优先级。Asio示例使用添加到优先级队列的自定义处理程序,然后在稍后的时间点执行这些处理程序
io\u service::run()
,这仍然是真的吗?谢谢Tanner的详细回复。strand肯定会有用的。由于我的io_服务只在一个线程中运行,并且在计划读取之前就请求取消(显然是这样),所以是否仍然可以先运行读取完成?@crmoore是的。io_服务
中处理程序的顺序未指定,并发级别不影响顺序。@StevenFaludi是的,仍然可以。串
将保证处理程序的顺序,而不是操作。如果acceptHandler
关闭oldConnectionSocket
,在newConnectionSocket
上启动读取操作,然后在oldConnectionSocket
上启动读取操作,则未指定调用和完成读取操作的顺序。因此,调用ReadHandler
s的顺序未指定。有关更多详细信息,请参阅答案。