У меня есть функция под названием read_packet. Эта функция остается заблокированной, пока нет запроса на соединение, или таймер сигнализируется.Boost.Asio: Почему таймер выполняется только один раз?
Код следующее:
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 (обрабатывается один дескриптор). Этот дескриптор соответствует таймеру.
Я не понимаю, почему возникает эта ситуация.
Почему функция не блокирует время, необходимое для таймера?
Cheers.
ПРИМЕЧАНИЕ: эта функция используется в цикле.
UPDATE:
У меня есть своя io_service::run()
функции. Эта функция выполняет другие действия и задачи. Я хочу слушать и обрабатывать сетевой уровень за определенный период времени:
Если что-то идет на уровне сети,
io_service::run_one()
возвращается и read_packet() возвращает управление моих запуска() функции.В противном случае таймер срабатывает и read_packet() возвращает управление к моей перспективе() функции.
Все, что поступает с сетевого уровня, хранится в структуре данных. Затем моя функция 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
}
}
В моем случае сокеты всегда активны, пока клиент не запросит закрытие соединения.
В течение временного интервала вы управляете уровнем сети, а для другого слота вы занимаетесь другими вещами.
Почему вы запускаете 'run_one', а не' run'? Кажется, что вы только один раз ждали, почему вы ожидаете, что таймер будет работать более одного раза? – sehe
@sehe: У меня есть асинхронный акцептор. По этой причине функция 'io_service :: run()' всегда заблокирована. Пока я жду подключения, я хочу выполнять другие задачи. Таймер позволяет мне это делать. –
Пожалуйста, посмотрите на некоторые образцы. Похоже, вы гремете против потока. Можете ли вы использовать поток для ввода-вывода или выполнять задания для ответных задач? Кроме того, это звучит как полное противоречие. Если вы используете таймеры для обратного вызова своего wiel, чтобы сделать в это время, в чем проблема с запуском, который не возвращается? Таймер по-прежнему будет гореть – sehe