我有一个名为 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
}
}
就我而言,套接字始终处于活动状态,直到客户端请求关闭连接。
在一个时间段内,您可以管理网络级别,也可以管理其他插槽。
答案 0 :(得分:0)
在仔细阅读问题之后,我意识到你实际上是在尝试使用Asio来获取同步IO,但每次读取操作都会超时。
这不是Asio的目的(因此,名称为“异步IO库”)。
但是当然,如果你坚持的话,你可以做到。就像我说的那样,我觉得你过于复杂。
在计时器的完成处理程序中,如果计时器已过期,则只需取消套接字操作。 (请注意,如果没有,您将获得operation_aborted
,因此请检查错误代码。)
小型自我包含的例子(顺便说一句,这是你在寻求帮助时应该经常做的事情):
<强> Live On 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
,其中概括了这个模式:
答案 1 :(得分:0)
好的,代码不正确。取消定时器时,始终执行定时器处理程序。因此,if(this.myControlForm.TabPages.Contains(tabPage1))
{
this.myControlForm.TabPages.Remove(tabPage1));
}
if(this.myControlForm.TabPages.Contains(tabPage2))
{
this.myControlForm.TabPages.Remove(tabPage2));
}
[...] //similar code for other tabPages
函数永远不会被阻止。
更多信息:basic_waitable_timer::cancel
感谢您的帮助。