boost async_wait () вызовет новый поток?

0

Мы должны часто вызывать метод для выполнения некоторых вычислений (около 20 раз в секунду). Это синхронизированный вызов. Вызывающий должен получить результат как можно скорее. Но этот процесс вычисления иногда занимает больше времени, чем ожидалось. Мы не хотим ничего менять. Мы просто хотим добавить какой-то механизм мониторинга, чтобы флаг приложения текущим вычислением был тайм-аутом, когда он переходит в течение ожидаемого периода времени.

У нас есть два варианта:

Опция 1:

создайте поток мониторинга на уровне класса, и он будет работать в течение всего срока службы приложения. Он начнет следить за тем, чтобы производительность метода вычислений всякий раз, когда он вызывается. Он будет сброшен при возврате вызова:

   monitorThread.startMonitoring();
   doComputation();
   monitorThread.stopMonitoring();

Когда вызывается startMonitoring(), working флаг будет установлен в true, а время начала будет установлено на текущее время на этом мониторе. он сможет узнать, является ли текущее состояние тайм-аутом или нет, когда он просыпается.

Когда вызывается stopMonitoring(), этот working флаг будет установлен в false, а monitorThread не будет проверять таймаут.

Вариант 2:

использовать boost dead_timer:

boost::asio::deadline_timer timer(io_service);
timer.expires_from_now(boost::posix_time::seconds(1));
timer.async_wait(handler);
doComputation();
timer.cancel();

Я не уверен, что опция dateline_timer будет работать для нас:

  1. могу ли я определить таймер на уровне класса и повторно использовать его во время всего сеанса работы приложения?
  2. вызывает ли вызов async_wait() новый поток в фоновом режиме? если да, возможно ли повторное использование этого потока снова и снова?

РЕДАКТИРОВАТЬ:

1. Если я использую следующий код внутри тела метода, обработчик будет вызван текущим потоком, а doComput() также будет работать в одном потоке. В случае doComput() зависать, как вызван обработчик?

boost::asio::deadline_timer timer(io_service);
timer.expires_from_now(boost::posix_time::seconds(1));
timer.async_wait(handler);
io_service.run(); // new added
doComputation();  // <<---- may hung sometime
timer.cancel();

2. Чтобы повторно использовать таймер и минимизировать количество потоков. Я должен создать экземпляр io_service в начале, т.е. поставить boost::asio::deadline_timer timer(io_service); в конструкторе. А также позвоните io_service.run(); в новом выделенном потоке (и пусть он умрет после вызова)? или просто вызвать его в главном потоке init, потому что io_service.run() начнет новый поток в любом случае? В том месте, где используется таймер, достаточно следующего фрагмента кода:

timer.cancel();
timer.expires_from_now(boost::posix_time::seconds(1));
timer.async_wait(handler);
doComputation();  // <<---- may hung sometime
timer.cancel();

Я прав?

Теги:
boost
boost-asio
boost-thread

1 ответ

3
Лучший ответ

могу ли я определить таймер на уровне класса и повторно использовать его во время всего сеанса работы приложения?

Да, вы можете повторно использовать таймер, т. Е. Снова вызвать expires_from_now() и async_wait() (но прочитайте ссылку, чтобы понять их поведение!).

вызывает ли вызов async_wait() новый поток в фоновом режиме? если да, возможно ли повторное использование этого потока снова и снова?

Нет (но в любом случае это деталь реализации). handler будет вызван из потока, выполняющего io_service::run().

Следуя вашему EDIT:

  1. Настоятельно рекомендуется ознакомиться с документацией Asio. Обратите внимание, что io_service::run() является блокирующим вызовом - он блокируется до тех пор, пока не будут вызваны все обработчики завершения. Вы можете рассматривать это как "цикл сообщений". Как правило, один вызывает его из выделенного потока. В качестве альтернативы можно опросить io_service вручную, вызывая poll()/poll_one() в некоторых других циклах, специфичных для приложения.

  2. io_service :: run() возвращается, когда он больше не работает, то есть нет ожидающих асинхронных операций и обработчиков завершения для отправки. Чтобы этот цикл сообщений выполнялся на протяжении всего срока службы вашего модуля (чтобы вы могли выполнять операции async.), Вам необходимо связать io_service::work с io_service.

  • 0
    Это означает, что я должен вызвать io_service :: run (), который будет запускать новый поток каждый раз?
  • 1
    @ 5YrsLaterDBA Почему каждый раз новая тема? Как правило, io_service::run() в потоке в течение всего срока службы приложения (или модуля). Затем вы можете использовать этот io_service для любого количества объектов Asio (таймеры, сокеты и т. Д.).
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню