Qt 5 : update QProgressBar during QThread work via signal

后端 未结 2 712
无人及你
无人及你 2020-12-16 08:51

I\'m trying to update a QProgressDialog (owned by a QMainWindow class) along the execution of a QThread who process some time consuming operations. The thread emit some sign

相关标签:
2条回答
  • 2020-12-16 09:13

    QThread has one very important thing you have to always remember when working with it - only the run() actually runs in a separate thread.

    Whenever you create an instance of QThread this instance's thread affinity (the thread it belongs to) is the same thread where you have created it in. What's the big deal with that and what does it have to do with my slots and signals you may ask? Well, it has a lot to do with these things. Because only run() runs inside a separate thread you have to consider the following:

    1. Signals belong to the instance ergo signals have a different thread affinity then the run()
    2. Slots belong to the instance ergo slots have a different thread affinity then the run() - accessing shared data that is processed both inside a slot and inside run() requires explicitly employing thread-safety mechanisms such as mutexes and semaphores
    3. If you do a lot of stuff inside your slots you will still freeze your UI as if you are not using your QThread

    That said there are some scenarios where you may want to/have to employ slots and signals in a QThread but such implementation would have to be directed towards controlling the instance of QThread and not what it's actually running in a separate thread (using run()).

    Here is a small demo I have written as a demonstration of how to implement slots and signals and interact with a separate thread using QObject. It employs slots and signals. Note that the usage of QThread is actually not necessary. You can also use a QRunnable for example (though you have to explicitly tell it to inherit from QObject too or to use a separate subclass of QObject created by you because QRunnable doesn't support slots and signals (it's not a subclass of QObject).

    The advantage of using a QObject is that you can move its instance to the thread that is change it's thread affinity so that it completely runs in that separate thread (slots included). You can also put multiple QObject instances inside a single QThread if you want to. When inheriting a QThread and using it instead of this model you are limiting your options quite a bit.

    So my advice here is dump the QThread implementation and go for the QThread + QObject (also know as Worker design pattern) way of doing things (for this particular scenario that is).

    0 讨论(0)
  • 2020-12-16 09:23

    Absolutely wrong using of QThread). See what is the correct way to implement a QThread... (example please...). You need to learn thread's basics.

    Your mistakes:
    1. Create a static thread object in a local scope;
    2. Wait for its finish in the main thread;
    3. Don't start the thread;
    4. Direct call method doHeavyCaclulations() in the main thread;
    5. emit signal without working event loop for its deliver...

    For your purpose you need:
    Don't inherit QThread. Just create simple Work class with the necessary function:

    class Work: public QObject
    {
        Q_OBJECT
    
    public:
        Work(){};
        virtual ~Work(){};
    
    public slots:
        void doHeavyCaclulations() { /* do what you need and emit progress signal */ };
    
    signals: 
        void progress(int);                
    }
    
    // Then:
    void QApp::doSomeWork()
    {
        //...
        QThread* thread = new QThread(parent);
        Work* worker = new Work; // Do not set a parent. The object cannot be moved if it has a parent. 
        worker->moveToThread(thread);
    
        connect(thread, SIGNAL(finished()), worker, SLOT(deleteLater()));
        connect(thread, SIGNAL(started()), worker, SLOT(doHeavyCaclulations()));
        connect(worker, SIGNAL(progress(int)), &progressDialog, SLOT(setValue(int)));
    
        thread->start();        
        //...
    }
    
    0 讨论(0)
提交回复
热议问题