我有一个派生自QCoreApplication
类的应用程序,并且有一个子线程成员。当我删除app对象时,它有时会删除。
class My_class :public QCoreApplication{
private:
My_object* obj;
QThread *th;
public:
My_class(){
obj=new My_object();
th= new QThread();
obj->movetoThread(th); // so it starts to run
}
~My_class(){
delete obj;
cout<<" App Destructor called"<<endl;
}
static void exit_(){quit();}
};
// So in main I suddenly close my application and i want to exit and delete obj;
int main()
{
My_class app;
signal(SIGTERM,&app.exit_);
signal(SIGINT,&app.exit_);
signal(SIGBREAK,&app.exit_);
return app.exec();
}
// The obj destructor is;
~My_object::My_object(){cout<<"Object dest called"<<endl;}
// The output of my program always writes "Object dest called"
//But sometimes writes " App Destructor called".
所以我的程序总是进入obj的destructpr
,但有时会进入app析构函数,有时不会。怎么可以实现?
答案 0 :(得分:0)
您可能有兴趣使用文档例程来记录应用程序销毁here。
在这种情况下,您可以注册一个post例程来清理存储在给定集合中的所有线程:
QList<QThread*> myThreads;
static void cleanup_threads()
{
foreach (QThread thread, myThreads) {
// cleanup the thread and delete it
}
}
int main(int argc, char **argv) {
QCoreApplication app(argc, argv);
qAddPostRoutine(cleanup_threads);
// setup signal handlers
// create threads
return app.exec();
}
除非您确切知道自己在做什么,否则这种做法可能非常危险。首选方法是创建另一个派生自QObject的类,您可以将您的主题提供给:
class MyThreadManager : public QObject {
MyThreadManager(QObject *parent = 0)
: QObject(parent)
{
for (int i = 0; i < 5; ++i) {
MyThread *thread = new MyThread(this);
// configure the thread object
thread->start();
// maybe add it to a local collection for later access:
// m_threads.append(thread);
}
}
};
int main(int argc, char **argv) {
QCoreApplication app(argc, argv);
// setup signal handlers
MyThreadManager manager;
return app.exec();
}
这样,你的所有线程都是同一个对象的父级,这个对象在被破坏时由父级的QObjectCleanupHandler清理。
答案 1 :(得分:0)
您将obj
移动到另一个主题:
My_class(){
obj=new My_object();
th= new QThread();
obj->movetoThread(th); // so it starts to run
}
QObject
只能从其主题中删除(如果有)。因此,这段代码是错误的:
~My_class() {
// You can't delete `obj` from a thread other than `th`!
delete obj;
cout<<" App Destructor called"<<endl;
}
你必须做的是先完成线程,然后才删除对象:
~My_class() {
th->quit();
th->wait();
delete th;
Q_ASSERT(obj->thread() == NULL); // thus it's safe to delete obj now!
delete obj;
}
这可以自动完成。我没有理由认为你应该将线程和对象保留在堆上。这是一种过早的悲观情绪。如果您打算在第一次使用时延迟构造对象及其线程,那么您应该使用智能指针:QScopedPointer
(或std::unique_ptr
,但不 {{1} })。
std::auto_ptr
这是有效的,因为在class Thread : public QThread {
using QThread::run; // It's a final class
public:
explicit Thread(QObject * parent = 0) : QThread(parent) {}
~Thread() { quit(); wait(); }
}
class My_Class : public QCoreApplication{
My_Object m_obj;
Thread m_thread; // Must be declared after any objects that live in it.
public:
My_Class(){
m_obj.moveToThread(&m_thread);
m_thread.start();
}
static void exit_() { quit(); }
};
之前m_thread
将被销毁。您可以而且应该利用C ++编译器为您生成正确的代码。毕竟,编译器总能正确使用它。