qt thread with movetothread

59,330

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.

Share:
59,330

Related videos on Youtube

unfamous
Author by

unfamous

Updated on January 12, 2020

Comments

  • unfamous
    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
    unfamous over 10 years
    ok thanks for your reply i thought that movetothread do the job . i'm going to use you idea
  • Kuba hasn't forgotten Monica
    Kuba hasn't forgotten Monica over 10 years
    It 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
    Kuba hasn't forgotten Monica over 10 years
    You 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
    Kuba hasn't forgotten Monica over 10 years
    The 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
    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 reimplement run() and call exec() yourself... but well good thing that QThread now offers a implementation of run() itself.
  • unfamous
    unfamous over 10 years
    thank you it worked . but now i get : get QObject: Cannot create children for a parent that is in a different thread.
  • jlunavtgrad
    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
    Kuba hasn't forgotten Monica over 10 years
    You 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
    Kuba hasn't forgotten Monica over 10 years
    smerlin: Kudos for a very nice answer.
  • Trilarion
    Trilarion over 8 years
    I 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
    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
    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
    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 before thread is deleted). I will update my answer nontheless to match this new offical example.