Results 1 to 4 of 4

Thread: Working properly with threads / QThreads

  1. #1
    Join Date
    Jun 2011
    Location
    Porto Alegre, Brazil
    Posts
    482
    Thanks
    165
    Thanked 2 Times in 2 Posts
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Working properly with threads / QThreads

    Hello!

    By now I've read the QtAssistant documentation regarding QThreads and even used a little of them in some projects, but to be honest I'm still not sure I'm working with them in the correct, safe method. To be more specific, I'm still not sure I understood the way by wich the run() method should be used alongisde the functions exec(), start(), quit(), terminate() and wait() as well as the use of flags to control the thread's event loop.

    To give some context, now I'm working on a project where I need to emit a signal each 250 ms and I decided it would be better to use a thred to do the work. So I need a event loop that, once the thread is started, will do the job, plus a previous configuration. The run() function, therefore, looked like this:

    Qt Code:
    1. void DataBrain::run()
    2. {
    3. qDebug() << "run()";
    4.  
    5. switch (source.principal)
    6. {
    7. case SourceInternet:
    8. switch (source.internet)
    9. {
    10. case SourceYahoo:
    11. connect(this,SIGNAL(signalUpdateData()),this,SLOT(slotUpdateYahoo()));
    12. break;
    13.  
    14. case SourceGoogle:
    15. connect(this,SIGNAL(signalUpdateData()),this,SLOT(slotUpdateGoogle()));
    16. D_TODO("DataBrain::run() | SourceGoogle");
    17. break;
    18.  
    19. default:
    20. M_BUG_OCCURANCE("DataBrain::run() | SourceInternet");
    21. break;
    22. }
    23. break;
    24.  
    25. case SourceRealTime:
    26. D_TODO("DataBrain::run() | SourceRealTime");
    27. break;
    28.  
    29. case SourceLocal:
    30. M_BUG_OCCURANCE("DataBrain::run()() | currentSource == SourceLocal");
    31. break;
    32. }
    33.  
    34. while(true)
    35. {
    36. emit signalUpdateData();
    37.  
    38. msleep(250);
    39. }
    40.  
    41. qDebug() << "run end";
    42. }
    To copy to clipboard, switch view to plain text mode 

    In doing so, I was expecting, given what I read in the QtAssistant data about QThread, that once I call the start() function from this thread, the run() function would be executed, doing the configuration and then running the event loop eternaly till a quit() or terminate() function was called, with the detail that if I call terminate(), the last qDebug() would never be called, while by using quit() it would since QtAssistant says that quit() ends the thread's event loop and finish it correctly (by which I understood: runs run() till the end). What I noticed, though, in a first moment was not just that the last qDebug() was never called, but also that if I called quit() and then start() again, the thread would immediately start again inside the while(true) code, never passing again by the configuration procedure and the first qDebug(). This was making quite the problem for my code till I was able to fix this, despite I still don't know exactly how ^^ (I guess it was because I put a "wait(500);" after my call of quit().

    I was beginning to think that my problem was solved when I read this topic in QtCentre: [http://www.qtcentre.org/threads/5590...qDebug+thread], where anda_skoa wrote that the proper way of handling a thread is to create a stop flag (that is, something like "while(flag)" instead of "while(true)"). I've done that already in previous works, but I still would like to know exactly why shouldn't I use my way, with the calling of quit(), instead of this flag-based method.

    More than that, it's still not clear to me when should I use terminate() instead of quit(), given the fact that that method is avaliable for us programmers to use despite being risky. Can I call it at least in a thread's destructor? And for what exactly the method exec() is used in thread programming, given the fact that there is the function start()? And also how exactly the method quit() works? And since we are already talking about threads, when exactly it's appropriate to use QSemaphore instead of QMutex/QMutexLocker and vice-versa?



    Thanks and sorry for too many questions in one topic.

    Momergil

  2. #2
    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: Working properly with threads / QThreads

    In order for quit to work the thread will need to run its event loop.
    That is what the QThread::run() base implementation does. If one overwrites run() then one can still start the event loop by calling exec().

    Qt Code:
    1. void MyThread::run()
    2. {
    3. // do some setup
    4.  
    5. exec(); // runs until quit is called
    6. }
    To copy to clipboard, switch view to plain text mode 

    I would stronlgy advise against calling terminate(), it can leave the program in state that it can not recover from.

    I am not really sure what your full use case is but calling a function regularily can easily be done without threads, e.g. using QTimer.

    Qt Code:
    1. DataBrain::DataBrain(Source source, QObject *parent) : QObject(parent)
    2. {
    3. QTimer *timer = new QTimer(this);
    4.  
    5. switch (source.principal)
    6. {
    7. case SourceInternet:
    8. switch (source.internet)
    9. {
    10. case SourceYahoo:
    11. connect(timer,SIGNAL(timeout()),this,SLOT(slotUpdateYahoo()));
    12. break;
    13.  
    14. case SourceGoogle:
    15. connect(time,SIGNAL(timeout()),this,SLOT(slotUpdateGoogle()));
    16. D_TODO("DataBrain::run() | SourceGoogle");
    17. break;
    18.  
    19. default:
    20. M_BUG_OCCURANCE("DataBrain::DataBrain() | SourceInternet");
    21. break;
    22. }
    23. break;
    24.  
    25. case SourceRealTime:
    26. D_TODO("DataBrain::DataBrain() | SourceRealTime");
    27. break;
    28.  
    29. case SourceLocal:
    30. M_BUG_OCCURANCE("DataBrain::DataBrain() | currentSource == SourceLocal");
    31. break;
    32. }
    33.  
    34. timer->start(250);
    35. }
    To copy to clipboard, switch view to plain text mode 
    Or putting that into a DataBrain::start() method, etc.

    And since we are already talking about threads, when exactly it's appropriate to use QSemaphore instead of QMutex/QMutexLocker and vice-versa?
    A binary semaphore, i.e. a QSemaphore which only ever has two values (0 and 1), is basically equivalent with QMutex. However, since there is no QMutexLocker equivalent, I would recommend using QMutex when the use case is to protect a generic critical section against concurrent access.

    The semaphore becomes interesting when it is being used with values n > 1, waiting for n threads to finish, or using it to enforce a resource usage limit, etc.

    Cheers,
    _

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

    Momergil (6th January 2014)

  4. #3
    Join Date
    Jun 2011
    Location
    Porto Alegre, Brazil
    Posts
    482
    Thanks
    165
    Thanked 2 Times in 2 Posts
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Working properly with threads / QThreads

    Hello anda_skoa,

    regarding the timer, I used it before, but since I wanted a little bit more of time precision, not to mention to relieve the main thread a little bit, I decided to put it inside a thread


    Thanks for the reply,

    Momergil

  5. #4
    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: Working properly with threads / QThreads

    Using a timer doesn't mean you can't use it in a thread.

    If you get this working like suggested in a QObject without a thread, then you can simply create a thread and move the object to it

    e.g.from
    Qt Code:
    1. DataBrain *dataBrain = new DataBrain;
    2. dataBrain->start();
    To copy to clipboard, switch view to plain text mode 
    to
    Qt Code:
    1. DataBrain *dataBrain = new DataBrain;
    2. QThread *thread = new QThread(this);
    3. dataBrain->moveToThread(dataBrain);
    4. connect(thread, SIGNAL(started()), dataBrain, SLOT(start()));
    5. connect(thread, SIGNAL(finished()), dataBrain, SLOT(deleteLater()));
    To copy to clipboard, switch view to plain text mode 

    If you still want to go for the run() re-implementation method, just ignore the signal/slot code that you currently have and call the methods from within your loop.

    Cheers,
    _

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

    Momergil (6th March 2014)

Similar Threads

  1. How to get properly working MinGW 4.4 ?
    By bisz in forum Installation and Deployment
    Replies: 0
    Last Post: 12th November 2013, 08:58
  2. Qt Creator Cmake is not working properly
    By Tabbu in forum Qt Tools
    Replies: 0
    Last Post: 12th January 2013, 08:38
  3. Replies: 1
    Last Post: 7th December 2011, 01:49
  4. memcpy not working properly
    By sattu in forum Qt Programming
    Replies: 3
    Last Post: 27th October 2010, 00:33
  5. ScrollZoomer not working properly..
    By Raghaw in forum Qwt
    Replies: 1
    Last Post: 30th October 2009, 07:51

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.