Results 1 to 5 of 5

Thread: Worker thread problem

  1. #1
    Join Date
    Sep 2008
    Posts
    18
    Thanks
    2
    Thanked 3 Times in 3 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Question Worker thread problem

    Hi everyone,

    I need some help with this problem I have... I'm trying to make a worker thread perform a long operation and have the GUI stay responsive. I need to give the thread a chunk of data to work on and let it run. I've read that the best way to pass data inbetween threads is signals and slots, so what I did is I subclassed a QThread like this (slightly simplified example: the thread gets a vector of floats and returns an image):

    Qt Code:
    1. class Worker : public QThread
    2. {
    3. Q_OBJECT
    4. public:
    5. void run();
    6. signals:
    7. void done(QImage);
    8. public slots:
    9. void makeImage(std::vector<float>);
    10. };
    11.  
    12. void Worker::run()
    13. {
    14. exec();
    15. }
    To copy to clipboard, switch view to plain text mode 

    The run() function just launches the event loop and at the end of makeImage slot I call exit(), I only need it to process the one signal. When the thread is done working it passes the result with the "done" signal. The vector type is registered with qRegisterMetaType() so it can be used with QueuedConnection.

    Now the (possibly) problematic code:
    Qt Code:
    1. Worker* worker = new Worker();
    2. connect(this, SIGNAL(makeImage(std::vector<float>)), worker, SLOT(makeImage(std::vector<float>)), Qt::QueuedConnection);
    3. connect(worker, SIGNAL(done(QImage)), this, SLOT(newImage(QImage)), Qt::QueuedConnection);
    4. worker->start();
    5. emit makeImage(my_vector);
    To copy to clipboard, switch view to plain text mode 

    I call for QueuedConnection explicitly to make sure the slot is called from the new thread.
    The problem is: it doesn't seem like a new thread is started at all, the GUI is blocked and when I call QThread::currentThread() from the working function, the result is the same as from the GUI thread! How come it's not spawning a new thread to do the work? If what I'm doing can be done better please tell me.

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Worker thread problem

    You're overcomplicating things. Try this:
    Qt Code:
    1. class Thread : public QThread {
    2. Q_OBJECT
    3. public:
    4. void Thread(QObject *parent = 0) : QThread(parent){}
    5. void setData(const std::vector<float> &dat){ m_d = dat; }
    6. void run(){ m_img = makeImage(m_d); }
    7. QImage image() const { return m_img; }
    8. private:
    9. std::vector<float> m_d;
    10. QImage m_img;
    11. };
    12. //...
    13. Thread *t = new Thread;
    14. t->setData(someData);
    15. connect(t, SIGNAL(finished()), this, SLOT(threadFinished()));
    16. t->run();
    17. //...
    18. void ...::threadFinished(){ Thread *thr = qobject_cast<Thread*>(sender());
    19. Q_ASSERT(thr);
    20. QImage image = thr->image();
    21. thr->deleteLater();
    To copy to clipboard, switch view to plain text mode 

    If you have multiple chunks to work on, there is a much simpler version:
    Qt Code:
    1. QImage makeImage(const std::vector<float> &data){
    2. // ...
    3. }
    4. //...
    5. QList<std::vector<float> > input;
    6. QFuture<QImage> result = QtConcurrent::mapped(input, makeImage);
    7. QFutureWatcher<QImage> *watcher = new QFutureWatcher(this);
    8. connect(watcher, SIGNAL(finished()), this, SLOT(operationFinished())); // or some other signal
    9. watcher->setFuture(result);
    To copy to clipboard, switch view to plain text mode 
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  3. #3
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Worker thread problem

    Hmm... actually you can simplify the first approach like this:
    Qt Code:
    1. QImage makeImage(const std::vector<float> &dat) {
    2. //...
    3. }
    4. // ...
    5. QFuture<QImage> future = QtConcurrent::run(makeImage, myData);
    6. QFutureWatcher *watcher = new QFutureWatcher(this);
    7. watcher->setFuture(future);
    8. connect(watcher, SIGNAL(finished()), this, SLOT(...)));
    To copy to clipboard, switch view to plain text mode 
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  4. The following user says thank you to wysota for this useful post:

    hkvm (6th September 2009)

  5. #4
    Join Date
    Sep 2008
    Posts
    18
    Thanks
    2
    Thanked 3 Times in 3 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Worker thread problem

    Woah this QtConcurrent stuff is mighty powerful, love Qt . Works perfecly now, thanks!

    Just a few corrections if more people use this: QFutureWatcher is also templated, so it should be QFutureWatcher<QImage>.
    And in the first suggested approach:
    Qt Code:
    1. Thread *t = new Thread;
    2. t->setData(someData);
    3. connect(t, SIGNAL(finished()), this, SLOT(threadFinished()));
    4. t->run();
    To copy to clipboard, switch view to plain text mode 
    Calling run() directly doesn't actually spawn a new thread, start() should be called instead and it runs run() in a thread (I tried this approach before using QtConcurrent, woked too but took much more boilerplate code).

  6. #5
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Worker thread problem

    Yeah, sorry, I didn't test this code prior to posting it
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


Similar Threads

  1. Problem with threads
    By kvnlinux in forum Newbie
    Replies: 7
    Last Post: 21st August 2009, 18:29
  2. Showing progress bar while worker thread works
    By olidem in forum Qt Programming
    Replies: 6
    Last Post: 27th April 2009, 21:43
  3. Workload in a QThread blocks main application's event loop ?
    By 0xBulbizarre in forum Qt Programming
    Replies: 14
    Last Post: 9th April 2006, 22:55
  4. Problem building Qt4.1.0 with thread support on windows XP
    By pavithra in forum Installation and Deployment
    Replies: 1
    Last Post: 1st April 2006, 12:35
  5. Replies: 2
    Last Post: 6th January 2006, 22:15

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.