QThread, How To Really, Truly Use



  • Hello,
    i tried to get an answer from Maya but maybe my question is too stupid :)
    I do not really understand this sentence from

    By the way, one extremely important thing to note here is that you should NEVER allocate heap objects (using new) in the constructor of the QObject class as this allocation is then performed on the main thread and not on the new QThread instance, meaning that the newly created object is then owned by the main thread and not the QThread instance. 
    

    Link: http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/

    If i create a new default qt application using the wizzard I get the Mainwindow constructor, the other constructor I have is the WORKERS constructor.

    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        QThread* thread = new QThread;
        Worker* worker = new Worker();
        worker->moveToThread(thread);
    ...
    

    Where exactly i NEVER should create the Thread and Worker instance ?
    Can do as in the MainWindow constructor above (in this simple code it works).
    Maybe someone has a complete little project how to do and how NEVER do.
    thx



  • Hi,
    I had seen already your reponse to the origioal thread of Maya. There I wondered already if you should stick too closely to what is written there. The summary has been created when there was Qt4 something. We have typically Qt 5 already. Therefore, a couple of things might have changed.
    Also if something was completely wrong in documentation back for Qt 4, it is likely that that has been corrected.
    Since there has been no followup for Qt5 based on the original summary, IMHO, I would rather rely more on current documentations (e.g. this) as a start. There are many different articles in the documentation, which certainly do not really make it less complex.



  • thnaks for reply. Yes, I use the actual docs (5.5).

    But did you understand this "NEVER"-sentence. Which constructor Maya meant
    in which never put the "new" commands ?
    The Workers constructor (make no sense for me at all)
    or
    the MainWindow constructor (what i did and works).
    If not in MainWindow constructor where else ?
    Or do you have an complete simple example how to or how never do it.



  • No. I am not really in details of threading yet.

    It might have something to do with the location of child objects of the object you are going to place in a different thread.

    Somewhere you can find that object with their childs are moved to the thread. This is in new documentation. Since I do not know what and how it was in Qt 4, I think it may be no longer a problem as it was possibly in Qt 4. Again I have the fuzzy feeling some statements of Maya's blog may be outdated because of change to Qt5. However, that is a lot of crystal ball reading from somebody with a huge lack of experience in the threading area.

    May be someone as @mcosta or others understand this senstence and give a proper answer.



  • OK, thnak you


  • Moderators

    Hi,

    @wally123 said:

    Where exactly i NEVER should create the Thread and Worker instance ?

    I wouldn't say "NEVER". The reason for that sentence is better explained in the QObject documentation (please read carefully the whole section about "Thread Affinity"):

    Note: A QObject's member variables do not automatically become its children. The parent-child relationship must be set by either passing a pointer to the child's constructor, or by calling setParent(). Without this step, the object's member variables will remain in the old thread when moveToThread() is called.

    Maya warned users not to create QObjects inside the Worker's constructor, because those QObjects would live in the original thread. However, if you set the parents correctly, all those QObjects would move to your new thread when you call worker->moveToThread(thread)



  • One simple alternative would be NOT to create any object in the constructor of the worker object, but instead create them inside an "init" slot which is called after the moveToThread.



  • Thanks for your efforts to explain, but i do not get it yet.
    Reading the entire docs confuse me even more.

    The QThread Docs (5.5) example uses:

    class WorkerThread : public QThread
    

    Question: Is this the sub-classing Maya mentioned in critic on Qt Docs ?

    "This should immediately show why the recommended way of using QThreads in the documentation, namely to sub-class it and implement your own run() function, is very wrong. (Maya) "

    Below i pasted a simple working code:

    1.) Is the following code correct or is this something NEVER to do ?
    2.) If this code is correct, how a "NEVER to do" but working code looks like ?
    (how to create a worker instance in the worker constructor ?)
    3.) If this code is correct, where is the associated correct parent setting ?

    //worker.h
    class Worker : public QObject
    {
        Q_OBJECT
    private:
    public:
        explicit Worker(QObject *parent = 0);
    signals:
        void finished();
        void error(QString);
    public slots:
        void process();
    };
    
    // worker.cpp
    #include "worker.h"
    Worker::Worker(QObject *parent) : QObject(parent)
    {
    
    }
    
    void Worker::process()
    {
        for(int i=0; i<10;i++) {
            qDebug() << this->thread()->objectName();
        }
        emit finished();
    }
    
    //mainwindow.cpp
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        QThread* thr_A = new QThread;
        thr_A->setObjectName("thr_A");
    
        Worker* worker_A = new Worker();
        worker_A->moveToThread(thr_A);
    
        connect(thr_A, SIGNAL(started()), worker_A, SLOT(process()));
        connect(thr_A, SIGNAL(finished()), thr_A, SLOT(deleteLater()));
        connect(worker_A, SIGNAL(finished()), thr_A, SLOT(quit()));
        connect(worker_A, SIGNAL(finished()), worker_A, SLOT(deleteLater()));
        connect(worker_A, SIGNAL(error(QString)), this, SLOT(errorString(QString)));
    
        thr_A->start(   );
    }
    
    void MainWindow::errorString(QString _err)
    {
        qDebug("Error");
    }
    

    thanks for patience :)


  • Moderators

    @wally123 said:

    class WorkerThread : public QThread
    

    Question: Is this the sub-classing Maya mentioned in critic on Qt Docs ?

    Yes, that is the sub-classing method that Maya criticized.

    Note: Maya's article is quite old, and it does not cover all use cases. The current QThread documentation is more complete. It says there are 2 ways to use QThread:

    1. Use a Worker QObject
    2. Subclass QThread

    To choose the "correct" way, you should ask yourself: Do you want to use signals and slots to communicate between threads?

    "This should immediately show why the recommended way of using QThreads in the documentation, namely to sub-class it and implement your own run() function, is very wrong. (Maya) "

    I disagree. Olivier Goffart disagrees too: http://woboq.com/blog/qthread-you-were-not-doing-so-wrong.html (Olivier is an expert who designed many core parts of Qt)

    Below i pasted a simple working code:

    1.) Is the following code correct or is this something NEVER to do ?

    Your code is correct.

    2.) If this code is correct, how a "NEVER to do" but working code looks like ?
    (how to create a worker instance in the worker constructor ?)

    There are many many ways to write bad code -- it's hard to show them all!

    3.) If this code is correct, where is the associated correct parent setting ?

    Your code does not require parenting, because your Worker object does not create any objects.



  • @JKSH
    much clearer now, wish I'll understand the docs also some day :)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.