Reputation: 608
I am learning how to run objects on different threads. I started with this simple exercise to run objects on different threads and communicate between them. Now, I have trouble terminating the program. How to safely destroy the objects running in different threads when main exits? If I put a wait on threads before main for the completion of threads, the program hangs at wait(). If I don't put a wait, threads are never executed and threads are deleted immediately as main exits.
--------testthread.h------------------
#ifndef TESTTHREAD_H
#define TESTTHREAD_H
#include <QThread>
#include <QApplication>
#include <string>
#include <iostream>
using namespace std;
class testThread : public QObject
{
Q_OBJECT
public:
testThread(const string&, QThread*);
~testThread();
private:
QThread* thread;
string _threadName;
signals:
void requestCalculateSquare(int);
public slots:
void calculateSquare(int);
void start();
};
#endif // TESTTHREAD_H}
-----testthread.cpp---------------------
#include "testthread.h"
#include <iostream>
//#include "moc_testthread.cpp"
testThread::~testThread()
{}
testThread::testThread(const string& threadName, QThread* thread):QObject()
{
_threadName = threadName;
moveToThread(thread);
connect(thread, SIGNAL(started()),this,SLOT(start()));
}
void testThread::calculateSquare(int i)
{
cout<<_threadName<<" "<<i*i;
}
void testThread::start()
{
for(int i=0;i<10;++i)
{
emit requestCalculateSquare(i);
}
emit finished();
}
--------main.cpp--------------------------
#include <iostream>
#include <QtCore/QCoreApplication>
#include <string>
#include "testthread.h"
using namespace std;
int main(int argc, char** argv)
{
QApplication app(argc,argv);
string name1("Thread1");
string name2("Thread2");
QThread* thread1 = new QThread;
QThread* thread2 = new QThread;
testThread* test1 = new testThread(name1, thread1);
testThread* test2 = new testThread(name2, thread2);
QObject::connect(test1,SIGNAL(requestCalculateSquare(int)),test2,SLOT(calculateSquare(int)));
QObject::connect(test2,SIGNAL(requestCalculateSquare(int)),test1,SLOT(calculateSquare(int)));
QObject::connect(test1,SIGNAL(finished()),test2, SLOT(deleteLater()));
QObject::connect(test1,SIGNAL(finished()),thread2, SLOT(quit()));
QObject::connect(test2,SIGNAL(finished()),test1, SLOT(deleteLater()));
QObject::connect(test2,SIGNAL(finished()),thread1, SLOT(quit()));
thread1->start();
thread2->start();
thread1->wait();
thread2->wait();
cout << "Hello World!" << endl;
return 0;
//return app.exec();
}
Upvotes: 2
Views: 3668
Reputation: 12693
You're doing some funky things.
1) Each QThread
is having start()
called twice - first in the testThread
constructor, then again in main()
. The second call won't do anything, since is is already running.
2) When you start the QThread
in the testThread
constructor, your loop will execute and emit the signals before they are connected - it makes me think you don't actually want to start the thread in the constructor, and instead leave it unstarted until later in main()
.
3) QThread::quit()
will cause the thread's event loop to return - this is what you're missing. connect
a "done" type signal from testThread
to the quit
slot, and then QThread::wait()
will behave as you expect, with the calls returning once the loops are completed.
4) I know it's just a little test program, but you're leaking memory since you aren't calling delete
on your new
objects. You actually don't need to use new
at all here, everything can be allocated on the stack - generally a better idea.
Upvotes: 3
Reputation: 24857
Don't do a wait on the threa\ds to prevent the main thread exiting. Wait on STDIN or some other input, perhaps?
wait/join to threads should only be done if absolutely required, (eg. a file has to be flushed/closed, a transaction has to be committed, a DB connection has to be closed). If you routinely join/wait on all threads just because it seems like a good idea, you will end up writing a whole load of complex code just to get threads to exit - something that is usually unnecessary.
Upvotes: 0