当任务所有者被销毁时,取消挂起的任务回调调用
Cancel pending task callback invocation when the task owner is destructed
我正在实现一个看起来像HTTP服务器的东西,设计是:对于一个已经建立的连接,我想在几个请求中重用它,所以当一个请求完成时,我用async_read
启动另一个读取任务,同时启动一个deadline_timer
。如果60秒内没有输入,计时器将被触发,连接将被破坏。让我恼火的是,在调用连接的析构函数之前,我们设置为async_read
的回调将被调用。
所以,我的问题是,有没有任何方法可以取消挂起的读取任务,即在不调用回调函数的情况下破坏连接?
如果上面的一般描述不清楚,详细的工作流程如下(代码附在底部):
请求完成时调用cleanup()
HandleTimeout()
,并且它调用stop()
stop()
中,进行清理工作,之后连接实例将被销毁但是,在步骤4之后,将调用callback()
函数,该函数已在AsyncRead()
中注册,那么,有什么方法可以取消对callback()
的调用吗?
代码:
class Connection : public boost::enable_shared_from_this<Connection>,
private boost::noncopyable {
public:
typedef Connection this_type;
void cleanup() {
timer_.expires_from_now(boost::posix_time::seconds(kDefaultTimeout));
timer_.async_wait(boost::bind(&this_type::HandleTimeout,
shared_from_this(),
boost::asio::placeholders::error));
AsyncRead();
}
void AsyncRead() {
boost::asio::async_read(*socket_, in_, boost::asio::transfer_at_least(1),
boost::bind(&this_type::callback,
shared_from_this(),
boost::asio::placeholders::error));
}
void callback(const boost::system::error_code& e) {
// ...
}
void HandleTimeout(const boost::system::error_code& e) {
if(e == boost::asio::error::operation_aborted)
LDEBUG << "The timeout timer is cancelled.";
else if(e)
LERROR << "Error occurred with the timer, message: " << e.message();
else if(timer_.expires_at()
<= boost::asio::deadline_timer::traits_type::now()) {
LDEBUG << "Connection timed out, close it.";
stop();
}
}
virtual void stop() {
connected_ = false;
socket_->close();
connection_manager_.stop(shared_from_this());
}
private:
// ...
boost::asio::deadline_timer timer_;
};
没有干净的方法可以实现这一点。确保不会调用准备运行的处理程序(如Connection::callback()
)的唯一方法是:
- 停止处理
io_service
事件循环 - 销毁
io_service
,因为io_service
的析构函数将导致销毁所有未完成的处理程序
在示例代码中,如果套接字不再打开,请考虑在Connection::callback()
中返回:
void callback(const boost::system::error_code& error)
{
if (!socket_.is_open()) return;
// ...
}
还要注意,error_code
参数不足以推断是否发生了超时。当socket::close()
被调用时,Connection::callback()
可能被排队等待boost::system::errc::success
的error_code
的调用。因此,没有可取消的操作。
相关文章:
- 挂起和取消挂起一个文件DLL
- 如何防止C++遗留代码中的挂起指针
- 为什么所有C++编译器都会崩溃或挂起此代码
- 我编写了代码将十进制分数转换为其二进制等效数.它编译得很好,但在执行时挂起
- 构建挂起,即使是适度的文件大小
- 循环挂起迭代的 std::擦除 on std::list
- Poco::Net::FTPClientSession 在 open() 方法上挂起 129 秒,如果 ftp 主机不存
- Node.js fs.open() 在尝试打开 4 个以上的命名管道 (FIFO) 后挂起
- 从不同进程中的另一个线程挂起/恢复线程或进程
- Boost (Beast) websocket:同步写入挂起
- 为什么析构函数挂起
- 使用互斥会挂起程序
- 在C++和 Python 程序中使用命名管道的 IPC 挂起
- 设置变量时C++程序挂起
- 第一次尝试使用new动态创建结构数组,程序挂起没有错误
- 从stdin读取时子进程挂起(fork/dup2竞争条件)
- 有时ShowWindow从不调用OnShowWindow,主应用程序挂起
- 如何防止GUI挂起,同时允许第二次操作与Qt中的第一次操作一起执行
- WTSFreeMemory在启动期间从服务调用时挂起-我应该省略吗
- 当任务所有者被销毁时,取消挂起的任务回调调用