I've got an application that receive a lot of data over the network via a QTcpSocket. If I keep the it all in the main thread, then the processor usage spikes and memory goes through the roof as there is no time left for processing events. I am trying to spin this processing off into a new object derived from QThread, and then use signals/slots to talk with the main thread.

The derived thread primarily does the following:
1) Receives data from the QTcpSocket.
2) Validates the data
3) Prepares the data for display
4) Sends 1 piece of data to the main application.
5) Upon receipt of #4, the main application sends the old data (if any) back to the thread for destruction.

Qt Code:
  1. // myObjectPtr is registered with qRegisterMetaType()
  2. // dataInfoObject is registered with qRegisterMetaType()
  3. // it's copy constructor initializes its QObject parent to NULL.
  4. class myThread : public QThread
  5. {
  6. Q_OBJECT
  7. Q_SIGNALS:
  8. void sendData(const myObjectPtr data);
  9. public Q_SLOTS:
  10. void setInfo(const dataInfoObject& _objectInfo);
  11. void setServer(const QString& _hostAddress, quint16 _hostPort);
  12. void getDataBack(const myObjectPtr data);
  13. protected Q_SLOTS:
  14. void dataAvailable();
  15. protected:
  16. // TCP Data STream
  17. QTcpSocket* myTcpConnection;
  18. // QObject derived class for information about the thread
  19. dataInfoObject* myInfo;
  20. void myThreadInit();
  21. public:
  22. myThread();
  23. ~myThread();
  24. void run();
  25. };
  26. ...
  27. myThread::myThread()
  28. {
  29. myInfo = NULL;
  30. myTcpConnection = NULL;
  31. }
  32. void myThread::run()
  33. {
  34. myThreadInit();
  35. exec();
  36. }
  37. void myThread::myThreadInit()
  38. {
  39. myInfo = new dataInfoObject(this);
  40. // connect internal stuff
  41. }
  42. void myThread::setServer(const QString& _hostAddress, quint16 _hostPort)
  43. {
  44. if (myTcpConnection == NULL)
  45. {
  46. myTcpConnection = new QTcpSocket(this);
  47. if (myTcpConnection != NULL)
  48. {
  49. // connect stuff up here - like readyRead(), connected(), etc.
  50. }
  51. }
  52. if (myTcpConnection != NULL)
  53. {
  54. myTcpConnection->connectToHost(_hostAddress,_port);
  55. }
  56. }
  57. ...
To copy to clipboard, switch view to plain text mode 

The derived thread's run() simply calls its exec(), which to my understanding is needed to use the thread's event queue and signals/slots.

The main thread creates a widget (which manages the display of the data), which creates the thread as part of its construction. After the thread is created, it connects several signals/slots for the two parts to communicate and then calls the thread's start.

Qt Code:
  1. class myWidget : public QWidget
  2. {
  3. Q_OBJECT
  4. ...
  5. private Q_SLOTS:
  6. void getData(const myObjectPtr data);
  7. Q_SIGNALS:
  8. void sendDataBack(const myObjectPtr data);
  9. void setThreadInfo(const dataInfoObject& _objectInfo);
  10. private:
  11. myThread workerThread;
  12. void createThread();
  13. protected:
  14. ...
  15. ...
  16. public:
  17. myWidget(QWidget* parent=NULL);
  18. };
  19. ...
  20. myWidget::myWidget(QWidget* parent) : QWidget(parent)
  21. {
  22. workerThread = NULL;
  23. ...
  24. createThread();
  25. }
  26. ...
  27. void myWidget::createThread()
  28. {
  29. if (workerThread == NULL)
  30. {
  31. workerThread = new myThread(this);
  32. }
  33. if (workerThread != NULL)
  34. {
  35. // connect stuff up - connection type not specified
  36. connect(this,SIGNAL(setThreadInfo(const dataInfoObject&)),workerThread,SLOT(setInfo(const dataInfoObject&)));
  37. ...
  38. workerThread->start();
  39. Q_EMIT setThreadInfo(threadInfo);
  40. }
  41. }
  42. ...
To copy to clipboard, switch view to plain text mode 

I just implemented the QThread in the last couple days; however, I discovered today that all the signal/slots are being handled in the main thread context, not the child thread's context. Thus the main thread is still chewing up all the processing time.

All the data getting passed over the signals/slots is either native to Qt, native C++ (e.g. bool, unsigned int, etc.), or it's been registered with the MetaObject system (via Q_DECLARE_METATYPE() and qRegisterMetaType()) so that it can be copied by Qt's event system.

I don't have any locks (yet) as I have not yet seen a need for them - the data is either in one context or the other, not both. I have also tried using the moveToThread() on the data object before emitting the signal with the object.

Qt Code:
  1. ...
  2. dataObject->(QApplication::instance()->thread());
  3. Q_EMIT sendData(dataObject);
  4. ...
To copy to clipboard, switch view to plain text mode 

One thing I have found is that when I initialize the data in the thread in myThreadInit() - I will get the error:

QObject: Cannot create children for a parent that is in a different thread.

if I provide a parent to the object even though it is creating it from within the thread's context.

Qt Code:
  1. // Generates: QObject: Cannot create children for a parent that is in a different thread.
  2. myInfo = new dataInfoObject(this);
  3.  
  4. // doesn't generate: QObject: Cannot create children for a parent that is in a different thread.
  5. myInfo = new dataInfoObject();
To copy to clipboard, switch view to plain text mode 

What am I doing wrong? What am I misunderstanding about QThreads?