qt thread with movetothread
Solution 1
The canonical Qt way would look like this:
QThread* thread = new QThread( );
Task* task = new Task();
// move the task object to the thread BEFORE connecting any signal/slots
task->moveToThread(thread);
connect(thread, SIGNAL(started()), task, SLOT(doWork()));
connect(task, SIGNAL(workFinished()), thread, SLOT(quit()));
// automatically delete thread and task object when work is done:
connect(task, SIGNAL(workFinished()), task, SLOT(deleteLater()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
in case you arent familiar with signals/slots, the Task class would look something like this:
class Task : public QObject
{
Q_OBJECT
public:
Task();
~Task();
public slots:
// doWork must emit workFinished when it is done.
void doWork();
signals:
void workFinished();
};
Solution 2
I don't know how you structured your process class, but this is not really the way that moveToThread works. The moveToThread function tells QT that any slots need to be executed in the new thread rather than in the thread they were signaled from. (edit: Actually, I now remember it defaults to the tread the object was created in)
Also, if you do the work in your process class from the constructor it will not run in the new thread either.
The simplest way to have your process class execute in a new thread is to derive it from QThread and override the run method. Then you never need to call move to thread at all.
Related videos on Youtube

unfamous
Updated on January 12, 2020Comments
-
unfamous almost 3 years
I'm trying to create a program using threads: the main start with a loop. When a test returns true, I create an object and I want that object to work in an other thread then return and start the test .
QCoreApplication a(argc, argv); while(true){ Cmd cmd; cmd =db->select(cmd); if(cmd.isNull()){ sleep(2); continue ; } QThread *thread = new QThread( ); process *class= new process (); class->moveToThread(thread); thread->start(); qDebug() << " msg"; // this doesn't run until class finish it's work } return a.exec();
the problem is when i start the new thread the main thread stops and wait for the new thread's finish .
-
unfamous over 10 yearsok thanks for your reply i thought that movetothread do the job . i'm going to use you idea
-
Kuba hasn't forgotten Monica over 10 yearsIt will only work that way if you never want any signals nor slots in your worker code. As soon as you do, it's easier to derive from QObject. You will normally want to have multiple worker QObjects per thread. The usual way of spawning a thread per each task to be done is, well, braindead. It adds thread switching overhead where none is needed.
-
Kuba hasn't forgotten Monica over 10 yearsYou can cheat and derive from QThread and add signals and slots to it, but it becomes really unintuitive. A QThread is an object that controls a thread. When you run QThread's slots within the thread itself, you create a Frankenstein that's both a thread controller and a thread. And, again, it becomes a single-purpose thread.
-
Kuba hasn't forgotten Monica over 10 yearsThe only reason to derive from QThread is... well, there's no reason. QThread spins an event loop and you can always move a QObject to it. That way your worker object's lifetime is not the same as the lifetime of the thread. Why not reuse the thread if there's more work to do? And so on... Qt's documentation entirely missed the point of explaining all this :(
-
smerlin over 10 years@KubaOber: There once was a reason... once upon a time
QThread
was an abstract class, and you had to derive and reimplementrun()
and callexec()
yourself... but well good thing thatQThread
now offers a implementation ofrun()
itself. -
unfamous over 10 yearsthank you it worked . but now i get : get QObject: Cannot create children for a parent that is in a different thread.
-
jlunavtgrad over 10 years@KubaOber:QThead only spins an event loop when you don't override run method. Or, if you do override the run method, you can start the event loop by calling exec. The way you use QThread is one way to do it, but not the only way.
-
Kuba hasn't forgotten Monica over 10 yearsYou must create those children from the
Task
code that already runs in the target thread, or before the object is moved to the target thread. -
Kuba hasn't forgotten Monica over 10 yearssmerlin: Kudos for a very nice answer.
-
Trilarion over 8 yearsI wonder what to do if you want to send parameters to doWork()? Could you send parameters directly or would you have to deliver them some other way. Then maybe using events would be better.
-
smerlin over 8 years@Trilarion: Either you pass parameters to the Task constructor and store them as member variables, or use the signal/slot system.
-
transistor over 5 years@smerlin: your code has a bug, the 3rd connect should use the task as source object, like in wiki.qt.io/QThreads_general_usage. Not doing so can lead to destruction failures.
-
smerlin almost 4 years@transistor I do not think this is an issue, since the objects should be deleted in the order of the connect calls (thus the
task
will be deleted beforethread
is deleted). I will update my answer nontheless to match this new offical example.