QThread blocking main application

10,067

Solution 1

Short answer: Start your thread by calling aThread->start(); not run(), and make sure you thread's run() method is protected (not public).

Explanation

Calling start() is the correct way to start the thread, as it provides priority scheduling and actually executes the run() method in its own thread context.

It looks like you are going to be loading images in this thread, so I'm going to include some tips before you run into pitfalls many people fall into while using QThread

  1. QThread itself is not a thread. It is just a wrapper around a thread, this brings us to..
  2. signals/slots defined in the CameraThread class will not necessarily run in the thread's context, remember only the run() method and methods called from it are running in a separate thread.

IMHO, subclassing QThread in the majority of cases is not the way to go. You can do it much simpler with the following code, and it will save you many headaches.

class ImageLoader : public QObject {
Q_OBJECT
public slots:
    void doWork() 
    {
        // do work
    }
};

void MainWindow::MainWindow(/*params*/) 
{
  ImageLoader loader;
  QThread thread;
  loader.moveToThread( &thread );
  connect( this, SIGNAL( loadImage() ), &loader ,SLOT( doWork() ) );
  thread.start();
  // other initialization
}
void MainWindow::LoadImage()
{
   emit loadImage();
}

Also read the Qt blog regarding this topic.

Solution 2

You have to call thread->start() not run... run is an entry point for thread. Thread is started with start. You call directly run, that's why you block your gui. Check documentation of QThread. virtual void QThread::run() is protected (not without a reason)

Share:
10,067
J W
Author by

J W

Updated on June 15, 2022

Comments

  • J W
    J W almost 2 years

    I have a simple form UI that has a slot for a button, starting a thread:

    void MainWindow::LoadImage()
    {
        aThread->run();
    }
    

    And the run() method looks like this:

    void CameraThread::run()
    {
        qDebug("Staring Thread");
        while(1)
        {
            qDebug("ping");
            QThread::sleep(1);
        }
    }
    

    When I click the button that calls LoadImage(), the UI becomes unresponsive. I periodically see the "ping" message as the debug output but the UI hangs, does not respond to anything. Why is my thread not running separately? CameraThread derived as public QThread I am using gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5) with QT libraries and QT Creator from Ubuntu 10.04(x86) repositories.

  • J W
    J W almost 14 years
    QT documentation explains usage of QThread by subclassing. Why is that a bad idea?
  • photo_tom
    photo_tom almost 14 years
    @Atilla - if you read QT Blog link in Casey's answer you will find it titled "You’re doing it wrong…". It is a discussion about why Qt's documentation about subclassing QThread was not the correct way to do threads. Also, if I've read the blog entry correctly, it is by the person who wrote the original Qt documentation.
  • emsiiggy
    emsiiggy almost 14 years
    Yes, thats correct. Basically, the Qt documentation is misleading and consequently has led many people to do hacky things (like movetoThread(this) in the Qthread constructor) that cause problems down the line. Hopefully the docs will be updated soon.
  • J W
    J W almost 14 years
    @photo_tom,@Casey, thank you both for clarifications. In my case, my separate thread does not have any slots, is supposed to run in a custom loop(continuously poll hardware) and only needs to occasionally inform the main app. So In my case, I believe subclassing is the correct way to go.
  • J W
    J W almost 14 years
    No, my problem was calling run() instead of start(). I already overrid run().
  • g19fanatic
    g19fanatic over 11 years
    I know this is a long dead question, but I have to disagree with subclassing A QThread object as the correct way to go... Still create your QObject and threadInstance.moveToThread(myObjInstance); but just have a slot that when called will loop forever (or until some condition variable gets changed, from another sig/slot connection). This has the added benefit of possibly using the same exact Thread for doing more stuff than just one Objects work (you can more as many objects as you want to a separate thread) So long as you do a processEvents in your cont loop, everything will be good.
  • g19fanatic
    g19fanatic over 11 years
    Its just bad OO to subclass a QThread object unless you're trying to do something special with threads, NOT just trying to run code on a different thread than your gui thread...