15

In my Qt application, I have a main thread and a worker thread. The worker thread subclasses QThread and processes events via customEvent. Is this the correct way for the main thread to send events to be processed by the worker thread?

QThread* myWorkerThread = // ...

QApplication::instance()->postEvent (myWorkerThread, new MyWorkRequestEvent(/* ... */);

If I read the documentation correctly, it states that events are processed on the thread of the object that own the event recipient. Since QThread was created by the main thread, it is owned by the main thread -- so would this event be processed by the main thread (which would be counter-intuitive, and in my case would be wrong)?

Tony the Pony
  • 40,327
  • 71
  • 187
  • 281

2 Answers2

16

Your understanding is correct and is indeed very unintuitive :)

A lot of the trouble comes from the documentation for QThread that suggests subclassing QThread. Although Qthread has its own event loop, only events and signals for QObjects created in the run() method (created in that thread) will be processed in the QThread event loop.

It is much better to encapsulate your thread logic in a QObject subclass and then move that object to an instance of a plain QThread. You can then communicate with that QObject using signals (which will be correctly queued across thread boundaries) or custom events.

There are some links in this similar question that should help.

Community
  • 1
  • 1
Arnold Spence
  • 21,942
  • 7
  • 74
  • 67
  • 4
    +1 for the 3rd paragraph: let's spread the correct way of threading – Máthé Endre-Botond Jun 01 '11 at 23:15
  • "`communicate with ... signals ... be correctly queued`" --- Both `QEvent` and signals are correctly executed. **But signal's *queued-connection* is expensive,** because first, each parameter gets serialized into `QByteArray`, then the other thread will automatically desterilize, of course, unless both sender and receiver are on the same thread. – Top-Master Jan 08 '23 at 20:55
  • I have a simple use case and I add to the constructor of my QThread subclass `moveToThread(this);`. This will make slots and events execute in the QThread's thread. – not-a-user Jan 09 '23 at 08:05
-1

Events are processed by the main event loop, which lives in QApplication or QCoreApplication. So it does not make sense to send events to QObjects in other threads (unless you create another event loop there which I am not sure is possible).

You can send events from other threads to your main thread, though. The myWorkerThread in your example is owned by the main thread, because it is created there. Objects created by your worker thread in run() and below are owned by this thread.

You also can send signals to slots in other thread, for example if you want to draw a widget (which must be done in the main thread) from your worker thread or similar.

Gunther Piez
  • 29,760
  • 6
  • 71
  • 103
  • 6
    QThreads do have their own event loop but events posted to the QThread itself will not be processed in that loop. – Arnold Spence Jun 01 '11 at 22:53
  • 1
    I just checked the doc, I didn't know that QThread has its own event loop ^^ But it needs to be explictly started with `exec()` which does not really make sense in a worker thread, because it will not return until `quit()` is called. – Gunther Piez Jun 01 '11 at 23:02