Results 1 to 7 of 7

Thread: QThread and GUI

  1. #1
    Join Date
    Jun 2012
    Posts
    173
    Thanks
    48
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default QThread and GUI

    Hello,

    I am trying to use QThread with GUI application, so the GUI wont stall on me.

    in th GUI, i have a window through witch i load a Txt file and parse it and do processing on it, they are in this manner

    Qt Code:
    1. loadFile (... )
    2. {
    3. readFile(..);
    4. parseFile(..);
    5. prossValues(...);
    6. }
    To copy to clipboard, switch view to plain text mode 

    when i run the loadFile slot, it takes long time, and the GUI stalls.

    what i did so far, is

    I sub-classed the QThread,
    override the run method and,
    emit a signal called loadFile(). in the run method.


    In the class where i need to load the file ,
    I create a mythread and,
    connect the loadFile signal to a loadFile slot.

    the the signal triggers fine and i load the file, but the gui still stalls,
    which i think it means that im still running on the main thread. not on the thread i created.

    so, Please let me know what im missing and what the mistake im making and how can i fix it.

    Thanks

    Jesse.
    Last edited by jesse_mark; 11th January 2013 at 18:48.

  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: QThread and GUI

    We'd need to see the actual code. Bear in mind that QThread object lives in the main thread and not in the thread it represents, that's probably your issue.

    Anyway, I suggest you use QtConcurrent::run() instead of a standalone QThread. For such simple usecases it's much easier to use.

    Qt Code:
    1. QString loadTextFile(const QString &fileName) {
    2. QFile f(fileName);
    3. if(!f.open(...)) return QString();
    4. QTextStream stream(&f);
    5. return stream.readAll();
    6. }
    7.  
    8. // ...
    9. QFutureWatcher<QString> *futureWatcher = new ...; // optional
    10. connect(futureWatcher, SIGNAL(finished()), this, SLOT(...))); // optional
    11. QFuture<QString> future = QtConcurrent::run(loadTextFile, QStringLiteral("somefile.txt"));
    12. futureWatcher->setFuture(future); // optional
    13.  
    14. // ... do something in the meantime
    15.  
    16. QString content = future.result(); // will block if the result is not ready (alternative to useing QFutureWatcher)
    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. The following user says thank you to wysota for this useful post:

    jesse_mark (11th January 2013)

  4. #3
    Join Date
    Jun 2012
    Posts
    173
    Thanks
    48
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QThread and GUI

    one of the reasons that im using Qthread, that i want to learn and understand how it works and how i can use it correctly.

    Here is the QThread subclass and the other class and i how i am using it.

    Qt Code:
    1. #ifndef MYTHREAD_H
    2. #define MYTHREAD_H
    3.  
    4. #include <QThread>
    5.  
    6. class MyThread : public QThread
    7. {
    8. Q_OBJECT
    9. public:
    10. explicit MyThread(QObject *parent = 0);
    11. void run();
    12.  
    13.  
    14. signals:
    15. void loadClicked();
    16.  
    17. public slots:
    18.  
    19. };
    20.  
    21. #endif MyTHREAD_H
    22.  
    23.  
    24.  
    25. //MyThread.c++
    26.  
    27. #include "mythread.h"
    28. #include "QtCore"
    29.  
    30. MyThread::MyThread(QObject *parent) :
    31. QThread(parent)
    32. {
    33.  
    34. }
    35. void MyThread::run()
    36. {
    37. qDebug() << "started...";
    38.  
    39. emit loadClicked();
    40.  
    41. }
    42.  
    43.  
    44.  
    45. //// Myclass.c++
    46. // Here it
    47. MyClass::Myclass(....)::QWidget(parent),
    48. ui(new Ui::MyClass)
    49. {
    50. ...
    51. ...
    52. loadThread = new Mythread(this);
    53.  
    54. connect (loadThread,SIGNAL(loadClicked),this, SLOT(loadFile));
    55. connect (loadThread,SIGNAL(finished),this, SLOT(onFinised));
    56. ...
    57. }
    58.  
    59. MyClass::onLoadFile_Clicked()
    60. {
    61. loadThread->start();
    62. }
    63.  
    64. MyClass::onFinised()
    65. {
    66. ...
    67. ....
    68. Qdebug() << "Finised.." ;
    69. }
    70.  
    71. void MyClass::loadFile ()
    72. {
    73. QStringList fileLines readFile(filename);
    74. result ParseFile(fileLines); // in this method i update the value of a progressBar
    75. prossResult (result); // in this method i update the value of a progressBar
    76. }
    77.  
    78. }
    To copy to clipboard, switch view to plain text mode 


    Added after 11 minutes:


    I think i understand what is my mistake now, Do i need to write all the loadFile code in the run method of the Thread ?, in other words all the work that i need to make it run by the thread should be written in the Mythread class ??? and then pass the result back where i want it ??
    Last edited by jesse_mark; 11th January 2013 at 21:37.

  5. #4
    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: QThread and GUI

    Well... what you code does is that it starts a thread, emits a signal from it and immediately ends the thread. Your slot is executed as usual in the main thread. What you are trying to do is really not a good usecase for a QThread. You can see that you have written almost 80 lines of code to do such a simple thing as loading a file (and it still doesn't work). The solution I gave you in 16 lines also uses a thread but is much more compact to write and easier to use. A good usecase for using QThread is when you want the thread to run for a longer time period, possibly waiting for more job to come. For a come-and-go situation, you're likely to waste more time starting the thread than gain from executing it. In turn Qt Concurrent keeps a number of threads at hand that may already be alive and just waiting for more work to appear in which situation the latency needed to start a thread is being amortized among tasks executed throughout the lifetime of the thread.

    If you insist on using QThread then I suggest that you don't subclass it. Instead push an object that will take care of parsing files to the thread and let it wait there for work, e.g.:

    Qt Code:
    1. class Parser : public QObject {
    2. Q_OBJECT
    3. public:
    4. Parser() {}
    5. public slots:
    6. void parseFile(const QString &fileName) {
    7. result r = doTheParsingHere(fileName);
    8. emit ready(r);
    9. }
    10. signals:
    11. void ready(result);
    12. };
    13.  
    14. // ...
    15.  
    16. QThread t; // create a thread controller (possibly a class member variable)
    17. t.start(); // start a thread
    18. Parser *p = new Parser; // create the parser object
    19. p->moveToThread(&t); // push it to the thread
    20. connect(p, SIGNAL(ready(result)), this, SLOT(useResult(result))); // connect to the result
    21.  
    22. // ...
    23.  
    24. QMetaObject::invokeMethod(p, "parseFile", Qt::QueuedConnection, Q_ARG(QString, "someFile.txt")); // make the parser do some work
    25. // or alternatively to the last line:
    26. connect(this, SIGNAL(parseRequested(QString)), p, SLOT(parseFile(QString)));
    27. emit parseRequested("someFile.txt");
    To copy to clipboard, switch view to plain text mode 

    That's still over 20 lines of code and the thread is running doing nothing most of the time so using QtConcurrent is still superior.
    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.


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

    jesse_mark (11th January 2013)

  7. #5
    Join Date
    Jun 2012
    Posts
    173
    Thanks
    48
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QThread and GUI

    Thank you so much for the clear explanation.

    I will diffidently go with the QtConcurrent::run method.

    Just to make things clear, the parsing the file may sound not taken too much time, but in this case I parse the file, i use the data parsed(process it) and then show the result. this all three steps takes a long time in my case as the lines i need to parse reach up to N=2 Millions lines and when i process them I need to go N*N as well.. which really take a long time.

    one Question regarding QtConcurrent::run, when I gave the method to QtConcurrent::run to run the method... is the thread that is used to run in it can reach the objects that are owned by the main thread.
    I mean such as the the editeLines, plot ...etc ?? as i need to reach them to read and update them during this process.

    Can I use it, to run the method, where the method reads some input from the UI objects ?? and then post other reseluts on the UI ??
    myMethod()
    {
    fileName = LineEdite->text();
    .....
    .....
    .....

    }


    I tried to call it like : QFutur<void> future = QtConcurrent::run(myMethod()); but it complains, so how i use it in this case ??

    Thanks

  8. #6
    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: QThread and GUI

    Quote Originally Posted by jesse_mark View Post
    Just to make things clear, the parsing the file may sound not taken too much time, but in this case I parse the file, i use the data parsed(process it) and then show the result. this all three steps takes a long time in my case as the lines i need to parse reach up to N=2 Millions lines and when i process them I need to go N*N as well.. which really take a long time.
    This might also be a task for QtConcurrent, QtConcurrent::mapped() or mappedReduced() this time.

    one Question regarding QtConcurrent::run, when I gave the method to QtConcurrent::run to run the method... is the thread that is used to run in it can reach the objects that are owned by the main thread.
    If you synchronize threads properly then yes, without proper synchronisation -- no.
    I mean such as the the editeLines, plot ...etc ?? as i need to reach them to read and update them during this process.
    No, you can't access GUI objects from threads other than the main thread, this will (eventually) lead to a crash.

    I tried to call it like : QFutur<void> future = QtConcurrent::run(myMethod()); but it complains, so how i use it in this case ??
    You have to pass a pointer to the function and not the result of the function call (as you do above). Take a look at the code I posted or read the docs (or both).
    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.


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

    jesse_mark (14th January 2013)

  10. #7
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: QThread and GUI

    I wouldn't use QtConcurrent::run() for loading.
    QtConcurrent::run() is based on the global thread pool and especially an I/O bound operation will keep anyone else waiting.

    I would rather go for my own threadpool instead.

    Cheers,
    _

    P.S. I also had the problem once that QtConcurrent::run() would execute in the calling thread. Might have been a bug (only occured on some users' systems). In any case I am not trusting that one anymore if I really require it to be run in a separate thread

  11. The following user says thank you to anda_skoa for this useful post:

    jesse_mark (14th January 2013)

Similar Threads

  1. Replies: 1
    Last Post: 4th October 2012, 14:49
  2. Need a little help with QThread
    By Slewman in forum Qt Programming
    Replies: 4
    Last Post: 15th March 2010, 20:04
  3. Replies: 4
    Last Post: 26th June 2008, 18:41
  4. Spawn a QThread in another QThread
    By david.corinex in forum Qt Programming
    Replies: 2
    Last Post: 19th December 2007, 12:54
  5. QThread?
    By vishal.chauhan in forum Newbie
    Replies: 4
    Last Post: 26th March 2007, 13:43

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.