multithreading - 创建新线程导致异常
问题描述
我有一个计时器,它将创建一个新线程并在调用通知函数之前等待计时器到期。它在第一次执行期间正常工作,但是当第二次启动计时器时,会抛出异常以尝试创建新线程。调试输出显示前一个线程在尝试创建新线程之前已经退出。
计时器.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;
};
计时器.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)
解决方案
如果只是测试
- 确保在调用析构函数时线程处理程序为空或加入。
- 使可以从多个线程访问的所有内容线程安全(特别是读取
active
标志)。简单地让它成为一个std::atomic_flag
应该做的事情。
看起来你正在杀死一个指向活动线程的线程句柄,但是如果没有看到整个应用程序就很难说。
如果不是测试
...然后通常,当需要一个计时器时,无论是否重复,您都可以将alarm()
信号安排到自身中。您仍然是完全单线程的,甚至不需要与pthread
库链接。这里的例子。
并且当期望需要更多计时器并保持一段时间时,值得将一个实例boost::asio::io_service
(或者asio::io_service
如果您需要一个无增强的仅标头版本)放入您的应用程序中,该应用程序具有成熟的生产就绪计时器支持。这里的例子。
推荐阅读
- ms-access - VBA中日期之间的总和
- python-3.x - Module.parameters() 如何找到参数?
- c++ - 如何在不使用 system() 的情况下使用 c++ 删除除最后 10 个文件之外的所有文件
- raku - Perl6:获取 Perl5 模块的数组引用
- python - Python 中用于提取特定字符串的正则表达式帮助,如下所示
- reactjs - 由于 lib.dom.d.ts 和 react-native 之间的标识符重复,TypeScript 编译失败
- mysql - mysql子查询?我的方法看起来像是一种廉价的方法
- android - 视图模型。设置数据
- tensorflow - 如何使用 TensorFlow tf.data.experimental.group_by_reducer
- javascript - CSS-如何在 i 标签悬停时显示面板