我正在尝试编写一个类,该类将在其对象创建时运行一个线程,并在对象被删除后停止该线程。
class MyThread : public boost::thread {
public:
MyThread() : bAlive(true) {
boost::thread(&MyThread::ThreadFunction,this);
}
~MyThread() {
{
boost::unique_lock<boost::mutex> lock(Mutex);
bAlive=false;
}
ConditionVariable.notify_one();
join();
}
private:
volatile bool bAlive;
boost::mutex Mutex;
boost::condition_variable ConditionVariable;
void ThreadFunction() {
boost::unique_lock<boost::mutex> lock(Mutex);
while(bAlive) {
ConditionVariable.timed_wait(lock,boost::get_system_time()+ boost::posix_time::milliseconds(MAX_IDLE));
/*******************************************
* Here goes some code executed by a thread *
*******************************************/
}
}
};
理论上,我想在线程需要完成时立即唤醒它,所以我不得不使用 timed_wait 而不是 Sleep。 这工作正常,直到我尝试删除此类的对象。在大多数情况下,它会正常删除,但偶尔会在 condition_variable.hpp、thread_primitives.hpp 或 crtexe.c 中导致错误。有时我会收到“释放堆 block 3da7a8 在释放后在 3da804 处修改”的通知,有时我不会。是的,我知道 timed_wait 的虚假唤醒,在这种情况下它并不重要。 你能指出我问题的根源吗?我做错了什么?
最佳答案
我明白你想做什么,但它没有像你预期的那样工作:
MyThread foo;
默认构造一个boost::thread(因为MyThread是从boost::thread派生的)。 默认构造函数创建一个引用 Not-a-Thread 的 boost::thread 实例。
MyThread() {
boost::thread(&MyThread::ThreadFunction,this);
}
实际上是在创建一个不同的线程,而您忽略了返回的对象(有效线程)。
~MyThread() {
// ...
join();
}
然后尝试加入默认构造的线程(它会在析构函数中引发异常),而您永远不会加入实际执行工作的线程。
首先,不要派生自boost::thread。创建一个成员变量:
class MyThread {
// ...
private:
// ...
boost::thread _thread;
};
在构造函数中,创建一个线程并将其分配给该成员变量:
MyThread() {
_thread = boost::thread(&MyThread::ThreadFunction,this);
}
并在你的析构函数中调用它的 join()。
~MyThread() {
// ...
_thread.join();
}
这应该可以解决您的问题。
但是,如果您只是想在对象被销毁时退出线程(并且不必在它运行时唤醒它),您可以使用不同的方法。删除互斥锁和条件变量并改用中断。这将导致 sleep() 抛出异常,因此您必须捕获它:
void ThreadFunction() {
try {
for(;;) {
boost::this_thread::sleep(boost::posix_time::milliseconds(MAX_IDLE));
// Here goes some code executed by a thread
}
} catch( const boost::thread_interrupted& e ) {
// ignore exception: thread interrupted, exit function
}
}
这将在线程中断时立即退出 ThreadFunction。如果不需要线程每个周期都休眠,可以用boost::this_thread::interruption_point()
代替。如果线程被中断,这只会抛出异常。
现在您可以简单地在析构函数中中断线程:
MyThread::~MyThread() {
_thread.interrupt();
_thread.join();
}
关于c++ - 删除 boost::thread 后代,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13323600/