我正在尝试编写一个相对简单的类'CallbackTimer',它需要一些时间和一个函数,并且在经过一段时间后调用该函数。如有必要,可以重复几次。
这一切都按预期工作,但是当我在计时器结束前调用启动几次时,我偶尔会遇到崩溃,但我看不出问题出在哪里。我认为这是因为我没有正确地混合我的线程和io_service,但我不确定。任何帮助或指示将不胜感激。
课程如下
CallbackTimer::CallbackTimer(const std::function<void()>& callback) :
callback_(callback),
currentRepeats_(0),
//io_(boost::asio::io_service()),
timer_(new boost::asio::deadline_timer(io_)),
strand_(io_),
thread_(nullptr)
{
}
CallbackTimer::~CallbackTimer()
{
cancel();
}
void CallbackTimer::start(size_t intervalMillis, int repeats)
{
if (thread_)
{
cancel();
}
requestedRepeats_ = repeats;
intervalMillis_ = intervalMillis;
currentRepeats_ = 0;
runTimer();
thread_.reset(new std::thread([this]()
{
this->io_.run();
}));
thread_->detach();
}
void CallbackTimer::cancel()
{
timer_->cancel();
if (thread_ && thread_->joinable())
{
thread_->join();
}
io_.reset();
}
void CallbackTimer::runCallback(const boost::system::error_code& e)
{
if (e == boost::asio::error::operation_aborted)
{
io_.stop();
return;
}
currentRepeats_++;
callback_();
if (currentRepeats_ >= requestedRepeats_)
{
io_.stop();
return;
}
runTimer();
}
void CallbackTimer::runTimer()
{
timer_->expires_from_now(boost::posix_time::millisec(intervalMillis_));
timer_->async_wait(strand_.wrap(std::bind(&CallbackTimer::runCallback, this, std::placeholders::_1)));
}
答案 0 :(得分:2)
快速浏览一下,有两个潜在的问题:
CallbackTimer
类无法保证在未完成对run()
,run_one()
,{{1}的调用时未调用io_service::reset()
的前提条件}或poll()
,导致未指定的行为。poll_one()
实例的生命周期结束后,可以调用CallbackTimer::runCallback()
,从而调用未定义的行为。这两个问题都是由于与运行CallbackTimer
的线程没有同步而导致的。线程在io_service
中创建后被分离,CallbackTimer::start()
中的if语句将始终为false,从而不会发生同步。这允许以下情况:
CallbackTimer::cancel()
在io_service::reset()
位于thread_
内时被调用。
io_service::run()
的{{1}}已取消分配,CallbackTimer
位于io_service
内。要解决此问题,请考虑不再从thread_
分离,以便可能发生同步。
为了进一步调试,堆栈跟踪或mcve可以帮助确定崩溃的确切来源。