我有一个计时器,它将创建一个新线程并等待计时器到期,然后再调用notify函数。它在第一次执行期间可以正常工作,但是在第二次启动计时器时,会尝试创建新线程时引发异常。 调试输出显示,在尝试创建新线程之前,先前的线程已退出。
Timer.hpp:
class TestTimer
{
private:
std::atomic<bool> active;
int timer_duration;
std::thread thread;
std::mutex mtx;
std::condition_variable cv;
void timer_func();
public:
TestTimer() : active(false) {};
~TestTimer() {
Stop();
}
TestTimer(const TestTimer&) = delete; /* Remove the copy constructor */
TestTimer(TestTimer&&) = delete; /* Remove the move constructor */
TestTimer& operator=(const TestTimer&) & = delete; /* Remove the copy assignment operator */
TestTimer& operator=(TestTimer&&) & = delete; /* Remove the move assignment operator */
bool IsActive();
void StartOnce(int TimerDurationInMS);
void Stop();
virtual void Notify() = 0;
};
Timer.cpp:
void TestTimer::timer_func()
{
auto expire_time = std::chrono::steady_clock::now() + std::chrono::milliseconds(timer_duration);
std::unique_lock<std::mutex> lock{ mtx };
while (active.load())
{
if (cv.wait_until(lock, expire_time) == std::cv_status::timeout)
{
lock.unlock();
Notify();
Stop();
lock.lock();
}
}
}
bool TestTimer::IsActive()
{
return active.load();
}
void TestTimer::StartOnce(int TimerDurationInMS)
{
if (!active.load())
{
if (thread.joinable())
{
thread.join();
}
timer_duration = TimerDurationInMS;
active.store(true);
thread = std::thread(&TestTimer::timer_func, this);
}
else
{
Stop();
StartOnce(TimerDurationInMS);
}
}
void TestTimer::Stop()
{
if (active.load())
{
std::lock_guard<std::mutex> _{ mtx };
active.store(false);
cv.notify_one();
}
}
错误从这里的代码块抛出:
thread = std::thread(&TestTimer::timer_func, this);
在第二次执行期间。
具体来说,该错误是从move_thread函数引发的:_Thr = _Other._Thr;
thread& _Move_thread(thread& _Other)
{ // move from _Other
if (joinable())
_XSTD terminate();
_Thr = _Other._Thr;
_Thr_set_null(_Other._Thr);
return (*this);
}
_Thrd_t _Thr;
};
这是一个例外:Unhandled exception at 0x76ED550B (ucrtbase.dll) in Sandbox.exe: Fatal program exit requested.
堆栈跟踪:
thread::move_thread(std::thread &_Other)
thread::operator=(std::thread &&_Other)
TestTimer::StartOnce(int TimerDurationInMS)
答案 0 :(得分:2)
如果只是测试
active
标志)。只需将其设置为std::atomic_flag
即可。看来您正在杀死指向活动线程的线程句柄,但是很难看到整个应用程序。
如果不是测试
...然后,通常,当需要单个计时器(是否重复)时,您可以自行安排一个alarm()
信号。您可以保持完美的单线程状态,甚至不需要与pthread
库链接。示例here。
并且当期望需要更多的计时器并保持一点时间时,值得将boost::asio::io_service
的实例(如果需要无增强的纯标题版本,可以将asio::io_service
的实例删除)具有成熟的生产就绪计时器支持的应用程序。示例here。
答案 1 :(得分:1)
您创建TestTimer
并通过TestTimer::StartOnce
第一次运行它,在此创建线程(在该行,稍后将引发异常)。线程完成后,它将在active = false;
中设置timer_func
。
然后,您第二次致电TestTimer::StartOnce
。与active == false
一样,当前线程上不会调用Stop()
,因此您将继续在thread = std::thread(&TestTimer::timer_func, this);
中创建一个新线程。
然后出现大的但是:
创建第二个线程之前,您尚未加入第一个线程。这就是它引发异常的原因。