deadline_timerが待っていません
-
28-10-2019 - |
質問
この簡単なテストアプリケーションでBoost Deadline_Timerを使用してみましたが、問題がありました。目標は、タイマーが45ミリ秒ごとにトリガーすることです。 expires_at()
のメンバー関数 deadline_timer
. 。 (私は絶対的な時間が必要なので、私は考えていません expires_from_now()
. 。私も現時点でドリフトについて心配していません)。プログラムを実行するとき、 wait()
45ミリ秒を待たない!しかし、エラーは報告されていません。私は何らかの形でライブラリを間違って使用していますか?
サンプルプログラム:
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>
using namespace std;
int main()
{
boost::asio::io_service Service;
boost::shared_ptr<boost::thread> Thread;
boost::asio::io_service::work RunForever(Service);
Thread = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&boost::asio::io_service::run, &Service)));
boost::shared_ptr<boost::asio::deadline_timer> Timer(new boost::asio::deadline_timer(Service));
while(1)
{
boost::posix_time::time_duration Duration;
Duration = boost::posix_time::microseconds(45000);
boost::posix_time::ptime Start = boost::posix_time::microsec_clock::local_time();
boost::posix_time::ptime Deadline = Start + Duration;
boost::system::error_code Error;
size_t Result = Timer->expires_at(Deadline, Error);
cout << Result << ' ' << Error << ' ';
Timer->wait(Error);
cout << Error << ' ';
boost::posix_time::ptime End = boost::posix_time::microsec_clock::local_time();
(cout << "Duration = " << (End - Start).total_milliseconds() << " milliseconds" << endl).flush();
}
return 0;
}
解決
現地時間とシステム時間を混ぜています。 ASIOが現地の時間を比較している時間は、締め切りがすぐに戻ってくる時間を設定してから数時間後になる可能性が高いです(住んでいる場所に応じて、この同じコードも数時間待つことができます)。この混乱の時点を避けるために、絶対時間はasio :: time_traitsに由来する必要があります。
#include <boost/asio.hpp>
#include <boost/asio/time_traits.hpp>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>
using namespace std;
typedef boost::asio::time_traits<boost::posix_time::ptime> time_traits_t;
int main() {
boost::asio::io_service Service;
boost::shared_ptr<boost::thread> Thread;
boost::asio::io_service::work RunForever(Service);
Thread = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&boost::asio::io_service::run, &Service)));
boost::shared_ptr<boost::asio::deadline_timer> Timer(new boost::asio::deadline_timer(Service));
while(1)
{
boost::posix_time::time_duration Duration;
Duration = boost::posix_time::microseconds(45000);
boost::posix_time::ptime Start = time_traits_t::now();
boost::posix_time::ptime Deadline = Start + Duration;
boost::system::error_code Error;
size_t Result = Timer->expires_at(Deadline, Error);
cout << Result << ' ' << Error << ' ';
Timer->wait(Error);
cout << Error << ' ';
boost::posix_time::ptime End = boost::posix_time::microsec_clock::local_time();
(cout << "Duration = " << (End - Start).total_milliseconds() << " milliseconds" << endl).flush();
}
return 0;
}
この場合、それはあなたのためにうまくいくはずです。
他のヒント
非同期方法を混合しています io_service::run
同期方法付き deadline_timer::wait
. 。これは機能しません。どちらかを使用します deadline_timer::async_wait
と io_service::run
, 、またはスキップします io_service::run
ただ使用してください deadline_timer::wait
. 。また、呼び出すスレッドは必要ありません io_service:run
非同期ルートに行くと、1つのスレッドが正常に行われます。どちらの概念も詳細に説明されています 基本的なスキル のセクション ASIOチュートリアル.
void print(const boost::system::error_code& /*e*/)
{
std::cout << "Hello, world!\n";
}
int main()
{
boost::asio::io_service io;
boost::asio::deadline_timer t(io, boost::posix_time::seconds(5));
t.async_wait(print);
io.run();
return 0;
}
あなたはあなたのためにいくつかの仕事をする必要があることに注意してください io_service
呼び出す前にサービスを提供します run()
. 。この例では、 async_wait
その仕事です。
潜在的に無関係:45msは非常に小さなデルタです。私の経験では、ハンドラーがASIO Epoll Reactorキューを通過するのに最小の時間は約30ミリ秒ですが、これはより高い負荷でかなり長くなる可能性があります。それはすべてあなたのアプリケーションに大きく依存していますが。