Results 1 to 4 of 4

Thread: Two threads in a console application

  1. #1
    Join Date
    May 2011
    Posts
    8
    Qt products
    Qt4

    Default Two threads in a console application

    Hello,

    Im developing a console application in which the main thread is continuously reading and parsing user input commands. One of that commands is called "loop" and with that I want to start loop after the user press ENTER and stops it when the user press ENTER again.

    So I have something like this:

    (MainThread)
    Qt Code:
    1. while(getchar() != '\n') QCoreApplication::processEvents();
    2. loop->start();
    3. while(getchar() != '\n') QCoreApplication::processEvents();
    4. loop->stop();
    To copy to clipboard, switch view to plain text mode 

    (ReadLoopThread)
    Qt Code:
    1. while(condition)
    2. {
    3. // read data from a serial device
    4. // print data on console
    5. // sleep 'x' miliseconds
    6. }
    To copy to clipboard, switch view to plain text mode 

    What's the correct way to implement this?

    I tried many solutions (none worked well):
    1) create a thread with a timer that emits a signal every 'x' miliseconds (avoiding the use of sleep()) and connected to a slot that reads data from serial device and print data in console if a global boolean variable is 'true' (meaning Im on the "loop" command); not efficient - timer is always emitting the signal
    2) two mutexes to control/block the loop as needed; it works but if I call QThread::sleep() it the thread blocks (why?)

    Now Im thinking on using .moveToThread() of QObject class but I really need to control the periodicity of loop and that way I guess I can't use QThread::sleep().

    The code in main():
    Qt Code:
    1. int main(int argc, char *argv[])
    2. {
    3. QCoreApplication a(argc, argv);
    4.  
    5. Commander *commander = new Commander();
    6. QObject::connect(commander, SIGNAL(end()), &a, SLOT(quit()));
    7. QTimer::singleShot(0, commander, SLOT(start())); // start the thread
    8. QTimer::singleShot(10, commander, SLOT(console())); // start console's loop
    9.  
    10. return a.exec();
    11. }
    To copy to clipboard, switch view to plain text mode 

    Commander inherits QThread. console() is the where I get (getline()) and parse user input.

    The ReadLoopThread:
    Qt Code:
    1. class ReadLoop : public QThread
    2. {
    3. Q_OBJECT
    4. public:
    5. ReadLoop(Commander *commander) {m_commander = commander;}
    6. public slots:
    7. void run();
    8. private:
    9. Commander *m_commander;
    10. };
    To copy to clipboard, switch view to plain text mode 

    Control implemented with mutexes:
    Qt Code:
    1. void ReadLoop::run()
    2. {
    3. forever
    4. {
    5. qDebug() << "readLoop is waiting to start";
    6. start_mutex.lock();
    7. start_mutex.unlock();
    8. while(!stop_mutex.tryLock())
    9. {
    10. qDebug() << "readLoop'ing";
    11. //QThread::sleep(1000); // DOESN'T WORK! Block the thread.
    12. // Without it, qDebug() executes "as fast as possible" - not acceptable
    13. }
    14. stop_mutex.unlock();
    15. }
    16. }
    To copy to clipboard, switch view to plain text mode 


    Any help is GREATLY appreciated.
    Last edited by msr; 26th September 2011 at 01:05.

  2. #2
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,709
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Two threads in a console application

    Let start with:
    Qt Code:
    1. while(getchar() != '\n') QCoreApplication::processEvents();
    2. loop->start();
    To copy to clipboard, switch view to plain text mode 
    loop->start() will never get called since you didn't use scope for the while().
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

  3. #3
    Join Date
    Sep 2011
    Posts
    1,245
    Thanks
    3
    Thanked 127 Times in 126 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Two threads in a console application

    Quote Originally Posted by high_flyer View Post
    Let start with:
    Qt Code:
    1. while(getchar() != '\n') QCoreApplication::processEvents();
    2. loop->start();
    To copy to clipboard, switch view to plain text mode 
    loop->start() will never get called since you didn't use scope for the while().
    start will be called when the condition is false.

  4. #4
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,709
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Two threads in a console application

    start will be called when the condition is false.
    Ah right - thats what happens when I read posts between compiles...

    1) create a thread with a timer that emits a signal every 'x' miliseconds (avoiding the use of sleep()) and connected to a slot that reads data from serial device and print data in console if a global boolean variable is 'true' (meaning Im on the "loop" command); not efficient - timer is always emitting the signal
    Well, not sure about "not efficient".
    Since you are not working with interrupts, you can't avoid polling.
    Running a timer might even be more efficient then a thread - as timer is triggered by a HW interrupt, while a thread is running all the time...
    If what ever milliseconds are good enough for you (and since you are reading from a serial port you probably wont need anything faster than 10ms per polling) this is the easier, and simpler solution, and probably more efficient too, which I would tend to do.

    2) two mutexes to control/block the loop as needed; it works but if I call QThread::sleep() it the thread blocks (why?)
    In your code I don't see where you defined and allocated your mutexes.
    Probably you have a thread affinity problem, so that you lock the same mutex twice before you unlock it.
    Also, you are misusing mutexes to what they are not intended.
    Which explains the code that makes little sense if you use mutexes as you should:
    Qt Code:
    1. start_mutex.lock();
    2. start_mutex.unlock();
    To copy to clipboard, switch view to plain text mode 
    Mutex is for protecting mutual exclusive data, not for conditional running.
    There are other mechanisms for that, such as semaphores or wait conditions.
    Just locking and immediately unlocking a mutex makes no sense if you are not protecting anything between the lock()/unlock(), and that code should be the same if you just delete both lines.
    I know what you wanted to achieve but that is the wrong way to go about it.
    As you are clearly not quite proficient with threading concepts, stick to the timer solution.
    It is a good solution, and a simple one.
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

Similar Threads

  1. How to exit Qt console application?
    By arcelivez in forum Qt Programming
    Replies: 14
    Last Post: 30th July 2014, 08:51
  2. about console application
    By jirach_gag in forum Qt Programming
    Replies: 2
    Last Post: 5th January 2012, 11:39
  3. Replies: 2
    Last Post: 21st November 2010, 18:03
  4. QT Console application QTextStream
    By Lis in forum Qt Programming
    Replies: 2
    Last Post: 6th November 2010, 05:18
  5. Exiting a Qt Console Application
    By nbetcher in forum Qt Programming
    Replies: 4
    Last Post: 23rd March 2009, 21:03

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.