Results 1 to 8 of 8

Thread: Problem with threads

  1. #1
    Join Date
    Aug 2009
    Location
    Moscow
    Posts
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Problem with threads

    Hi,

    i wrote a simple program, that queries the COM port. GUI specifies the data, that is sent to port, and displays the data it receives. so, my code looks like this:
    Qt Code:
    1. /* main.cpp */
    2. #include <QtGui/QApplication>
    3. #include "mainwindow.h"
    4. #include "Thread.h"
    5.  
    6. int main(int argc, char *argv[]) {
    7. QApplication app(argc, argv);
    8. MainWindow window;
    9. Thread thread;
    10. QObject::connect(&thread, SIGNAL(update(int)), &window, SLOT(update(int)));
    11. thread.start();
    12. window.show();
    13. int status = app.exec();
    14. thread.stop();
    15. thread.wait(1000);
    16. return status;
    17. }
    To copy to clipboard, switch view to plain text mode 
    Qt Code:
    1. /* Thread.h */
    2. #include <QThread>
    3. #include <QTimer>
    4.  
    5. class Thread : public QThread
    6. {
    7. Q_OBJECT
    8. public:
    9. Thread();
    10. void run();
    11. signals:
    12. void update(int);
    13. public slots:
    14. void stop();
    15. void doAction();
    16. private:
    17. QTimer timer;
    18. };
    To copy to clipboard, switch view to plain text mode 
    Qt Code:
    1. /* Thread.cpp */
    2. #include "Thread.h"
    3.  
    4. Thread::Thread() {
    5. timer.setInterval(1000);
    6. connect(&timer, SIGNAL(timeout()), this, SLOT(doAction()));
    7. connect(this, SIGNAL(started()), &timer, SLOT(start()));
    8. }
    9.  
    10. void Thread::run() {
    11. exec();
    12. }
    13.  
    14. void Thread::stop() {
    15. timer.stop();
    16. this->quit();
    17. }
    18.  
    19. void Thread::doAction() {
    20. here i write some data to port and then get some data
    21. emit update(some data);
    22. }
    To copy to clipboard, switch view to plain text mode 

    MainWindow is a simple window, that has a slot update.
    So, the problem is that, when port is unavailable or doesn't return data, thread is trying to obtain data for several times. This operation lasts for a second and my GUI freezes for this time. I've read a nuber of books and it seems to me that my code doesn't differ from that given in the examples. Also, i haven't got this problem when i don't use event loop in my thread that is when i use msleep and while statement in QThread::run() function.

    So, could anyone explain me what's wrong with my code and how could i solve this problem.
    Thanks in advance.

  2. #2
    Join Date
    Jun 2008
    Location
    Germany/Belarus/Sweden
    Posts
    53
    Thanks
    3
    Thanked 1 Time in 1 Post
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Problem with threads

    Qt Code:
    1. void Thread::run() {
    2. exec();
    3. }
    To copy to clipboard, switch view to plain text mode 
    You do nothing in your thread. Only run() function is real thread and runs in another stream. all other functions in class is just for more accurate OOP. So your Thread::doAction() runs in the same thread as GUI, that is why you have freezes.

  3. #3
    Join Date
    Jul 2009
    Location
    Enschede, Netherlands
    Posts
    462
    Thanked 69 Times in 67 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Problem with threads

    This means that you have to define a QObject inside the run() function; one that actually lives in another thread. Then you can use the timer to tell that QObject to doAction().
    Horse sense is the thing that keeps horses from betting on people. --W.C. Fields

    Ask Smart Questions

  4. #4
    Join Date
    Sep 2008
    Location
    Bangalore
    Posts
    659
    Thanks
    116
    Thanked 42 Times in 41 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Problem with threads

    Qt Code:
    1. void Thread::run() {
    2. exec();
    3. }
    To copy to clipboard, switch view to plain text mode 

    u can do all doAction() work inside run() itself ...
    Qt Code:
    1. void ::run()
    2. {
    3. while(stopped){
    4. here i write some data to port and then get some data
    5. emit update(some data);
    6. sleep(1);
    7. }
    8. }
    9.  
    10. void Thread::stop() {
    11. stopped = true;
    12. wait();
    13. }
    To copy to clipboard, switch view to plain text mode 

    and no need to call QThread::exec();(protected) seperately as QApp->exec(); is enough
    "Behind every great fortune lies a crime" - Balzac

  5. #5
    Join Date
    Aug 2009
    Location
    Moscow
    Posts
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Problem with threads

    Quote Originally Posted by franz View Post
    This means that you have to define a QObject inside the run() function; one that actually lives in another thread. Then you can use the timer to tell that QObject to doAction().
    Ok, i've rewrite it, so at the moment it looks like this
    Qt Code:
    1. /* Thread.h */
    2. #include <QThread>
    3.  
    4. class Object : public QObject
    5. {
    6. Q_OBJECT
    7. public:
    8. Object();
    9. protected:
    10. void timerEvent(QTimerEvent*);
    11. signals:
    12. void update(int);
    13. private:
    14. int timerId;
    15. }
    16.  
    17. class Thread : public QThread
    18. {
    19. Q_OBJECT
    20. public:
    21. Thread();
    22. void run();
    23. private:
    24. Object* object;
    25. };
    To copy to clipboard, switch view to plain text mode 
    Qt Code:
    1. /* Thread.cpp */
    2. #include "Thread.h"
    3.  
    4. Thread::Thread() {
    5. }
    6.  
    7. void Thread::run() {
    8. object = new Object();
    9. exec();
    10. }
    11.  
    12. Object::Object() {
    13. timerId = startTimer(1000);
    14. }
    15.  
    16. Object::~Object() {
    17. killTimer(timerId);
    18. }
    19.  
    20. void Object::timerEvent(QTimerEvent* event) {
    21. here i write some data to port and then get some data
    22. emit update(some data);
    23. }
    To copy to clipboard, switch view to plain text mode 
    As i understood, you advised me to create an object inside QThread::run() function and then to use a timer for this object. Unfortunately, GUI is steel freezing when this object is trying to read from port. Maybe, i've missed something?

  6. #6
    Join Date
    Jul 2009
    Posts
    139
    Thanks
    13
    Thanked 59 Times in 52 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Problem with threads

    Your code works fine for me (with a sleep call in timerEvent). The update slot will run in the GUI thread, are you doing anything that could cause a freeze in that function?

  7. #7
    Join Date
    Aug 2009
    Location
    Moscow
    Posts
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Problem with threads

    Quote Originally Posted by numbat View Post
    Your code works fine for me (with a sleep call in timerEvent). The update slot will run in the GUI thread, are you doing anything that could cause a freeze in that function?
    No, inside timerEvent function i just write data to COM port and then read from port. The only thing that is slow enough is reading data from port, when there is no data to read. In this case i do up to 10 attempts to read and then return either a piece of data or error. But this function is performed within the separate thread, so it shouldn't influence the GUI thread. Update slot in GUI displays the value from timerEvent function in QLCDNumber.

    Anyway, i'll rewrite my code step by step to find what causes GUI to freeze.
    Thank you all, i really appreciate your help, since this is my first experience of working with threads.

  8. #8
    Join Date
    Mar 2009
    Posts
    98
    Thanks
    3
    Thanked 9 Times in 9 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Problem with threads

    Why you check the serial port with a timer instead of doing it directly in the run() of the thread?

    I use QextSerialPort and I check the available data in a thread like this:

    Qt Code:
    1. class ReceiveThread : public QThread
    2. {
    3. Q_OBJECT
    4.  
    5. public:
    6. ReceiveThread(QextSerialPort *adrPort);
    7. ~ReceiveThread();
    8.  
    9. void stopReceiving();
    10.  
    11. protected:
    12. void run();
    13.  
    14. signals:
    15. void dataReceived(const QByteArray); //!< Data Available from the QextSerialPort
    16.  
    17. private:
    18. QextSerialPort *d_port; //!< Reference to the serial port to monitor
    19. QMutex mutex; //!< Mutex lock
    20. bool stopped; //!< Specify if the thread is running or not (it is needed to stop the thread)
    21. };
    22.  
    23. ReceiveThread::ReceiveThread(QextSerialPort *adrPort)
    24. : d_port(adrPort), stopped(false)
    25. {
    26. }
    27.  
    28. ReceiveThread::~ReceiveThread()
    29. {
    30. if (isRunning())
    31. {
    32. stopReceiving();
    33. wait();
    34. }
    35. }
    36.  
    37. void ReceiveThread::stopReceiving()
    38. {
    39. stopped = true;
    40. }
    41.  
    42. //! The Receive Thread Loop
    43. void ReceiveThread::run()
    44. {
    45. QByteArray data;
    46. int bytesAvailable;
    47. data.reserve(MAX_BUFFER_SIZE);
    48.  
    49. while(!stopped)
    50. {
    51. mutex.lock();
    52. bytesAvailable = d_port->bytesAvailable();
    53. if (bytesAvailable > 0)
    54. data.append(d_port->read((bytesAvailable<MAX_BUFFER_SIZE)? bytesAvailable: MAX_BUFFER_SIZE));
    55. mutex.unlock();
    56.  
    57. if (bytesAvailable)
    58. qDebug() << tr("ReceiveThread: %1").arg(bytesAvailable);
    59.  
    60. if (!data.isEmpty())
    61. {
    62. emit dataReceived(data);
    63. qDebug() << tr("ReceiveThread: Emitted Data Received");
    64. qDebug() << tr("ReceiveThread: Data: 0x%1").arg((QString)data.toHex());
    65. data.clear();
    66. }
    67.  
    68. msleep(RECEIVE_THREAD_SLEEP_TIME);
    69. }
    70. }
    To copy to clipboard, switch view to plain text mode 

    To use this class you only nead to istantiete the class and call the run() method to start the monitoring of the serial port.
    To stop the monitoring you must call the stopReceiving() method.

    The data received is emitted with the signal dataReceived(const QByteArray &), so you have to connect this with a slot to manage the data received.

    WARNING
    This class does not perform any check on the QextSerialPort provided, you have to perform these check before starting the Receive Thread. Also you have to stop the Receive Thread before close the QextSerialPort.

    So, instead to instantiate the Thread directly in the Main you have to instantiate it in your MainWindow after create and open the serialport.

Similar Threads

  1. problem with opengl, zooming, drawpixels, and origin
    By ntp in forum General Programming
    Replies: 0
    Last Post: 22nd February 2008, 21:48
  2. Tricky problem with ARGB widget / UpdateLayeredWindow
    By nooky59 in forum Qt Programming
    Replies: 3
    Last Post: 21st February 2008, 10:35
  3. Problem creating a QWidget using threads
    By tarod in forum Qt Programming
    Replies: 1
    Last Post: 16th November 2007, 12:45
  4. fftw problem
    By lordy in forum General Programming
    Replies: 1
    Last Post: 16th March 2006, 21:36
  5. Problems with threads and windows
    By SkripT in forum Qt Programming
    Replies: 15
    Last Post: 16th January 2006, 17:46

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.