阿西奥:为什么计时器只执行一次
Boost.Asio: Why the timer is executed only once?
我有一个名为read_packet的函数。在没有连接请求或计时器发出信号时,此功能仍被阻止。
代码如下:
std::size_t read_packet(const std::chrono::milliseconds& timeout,
boost::system::error_code& error)
{
// m_timer_ --> boost::asio::high_resolution_timer
if(!m_is_first_time_) {
m_is_first_time = true;
// Set an expiry time relative to now.
m_timer_.expires_from_now( timeout );
} else {
m_timer_.expires_at( m_timer_.expires_at() + timeout );
}
// Start an asynchronous wait.
m_timer_.async_wait(
[ this ](const boost::system::error_code& error){
if(!error) m_is_timeout_signaled_ = true;
}
);
auto result = m_io_service_.run_one();
if( !m_is_timeout_signaled_ ) {
m_timer_.cancel();
}
m_io_service_.reset();
return result;
}
在未接收到连接请求的情况下,该功能正常工作。所有请求的接受都是异步的。
接受连接后,run_one()函数不会在计时器设置的时间内保持阻塞状态。函数总是返回1(已处理一个句柄)。此句柄对应于计时器。
我不明白为什么会出现这种情况。
为什么功能没有阻止计时器所需的时间?
干杯。
注意:此函数用于循环中。
更新:
我有自己的io_service::run()
函数。此功能执行其他操作和任务。我想在一段时间内收听和处理网络级别:
如果某个东西出现在网络级别,
io_service::run_one()
将返回,read_packet()将控件返回给我的run()数。否则,计时器将被触发,read_packet()将控件返回给我的run()函数。
来自网络级别的所有内容都存储在数据结构中。然后我的run()函数对该数据结构进行操作。它还运行其他选项。
void run(duration timeout, boost::system::error_code& error)
{
time_point start = clock_type::now();
time_point deadline = start + timeout;
while( !stop() ) {
read_packet(timeout, error);
if(error) return;
if(is_timeout_expired( start, deadline, timeout )) return;
// processing network level
// other actions
}
}
在我的情况下,套接字始终处于活动状态,直到客户端请求关闭连接。
在一个时间段内,您可以管理网络级别,而在另一个时间段里,您可以做其他事情。
仔细阅读这个问题后,我发现您实际上是在尝试使用Asio来获得同步IO,但每次读取操作都会超时。
这并不是Asio的初衷(因此得名"异步IO库")。
但当然,如果你坚持,你可以做到。就像我说的,我觉得你把事情搞得太复杂了。
在计时器的完成处理程序中,如果计时器已过期,只需取消套接字操作即可。(请注意,如果没有,您将得到operation_aborted
,因此请检查错误代码)。
小的自我包含的例子(顺便说一句,这是你在寻求帮助时应该做的事情):
在Coliru上直播
#include <boost/asio.hpp>
#include <boost/asio/high_resolution_timer.hpp>
#include <iostream>
struct Program {
Program() { sock_.connect({ boost::asio::ip::address_v4{}, 6771 }); }
std::size_t read_packet(const std::chrono::milliseconds &timeout, boost::system::error_code &error) {
m_io_service_.reset();
boost::asio::high_resolution_timer timer { m_io_service_, timeout };
timer.async_wait([&](boost::system::error_code) {
sock_.cancel();
});
size_t transferred = 0;
boost::asio::async_read(sock_, boost::asio::buffer(buffer_), [&](boost::system::error_code ec, size_t tx) {
error = ec;
transferred = tx;
});
m_io_service_.run();
return transferred;
}
private:
boost::asio::io_service m_io_service_;
using tcp = boost::asio::ip::tcp;
tcp::socket sock_{ m_io_service_ };
std::array<char, 512> buffer_;
};
int main() {
Program client;
boost::system::error_code ec;
while (!ec) {
client.read_packet(std::chrono::milliseconds(100), ec);
}
std::cout << "Exited with '" << ec.message() << "'n"; // operation canceled in case of timeout
}
如果套接字操作成功,您可以看到例如:
Exited with 'End of file'
否则,如果操作没有在100毫秒内完成,它将打印:
Exited with 'Operation canceled'
另请参阅前面的答案中的await_operation
,它进一步概括了这种模式:
- boost::asio+std::future-关闭套接字后发生访问冲突
好的,代码不正确。当计时器被取消时,计时器处理程序总是被执行。因此,io_service::run_one()
功能从未被阻止。
更多信息:basic_waitable_timer::取消
谢谢你的帮助。
- 为什么我的信号处理程序只执行一次?
- 调用函数一次用于动态链接库,一次从可执行文件调用函数
- For循环在cpp中仅执行一次
- 在可变函数调用中执行一次语句
- 如何强制循环执行另一次迭代到零并关闭循环
- 为什么我的 cout 一次执行,尽管 cin 应该在两者之间读取?
- cppUnit:针对多个测试方法执行一次的设置函数
- For 循环是否总是至少执行一次?
- 仅执行一次函数一次内部循环,该循环在每个0.1秒C 处都被调用
- 代码执行/CPU 速度每 2 秒减慢一次
- 函数被多次执行,同时调用一次
- 如何确保方法在该对象的生存期内仅执行一次?
- 一次遍历 8 个向量字节并执行按位运算
- OpenMP 一次只执行一个线程
- 线程仅执行一次
- while(getline(myReadFile, temp, ':')) 执行一次迭代太多导致向量越界
- C++,查找最低值,函数错误:循环最多运行一次(循环增量从未执行)
- Qt - 解决一个插槽上的两个顺序调用,并且仅执行一次操作
- 调用从上一次执行中保存的函数指针会失败吗
- 一次执行后,嵌套for循环出现意外/未见的中断:高斯消去