arc_lupus
arc_lupus

Reputation: 4114

How to write a second thread which listens to incoming signals?

I have a question concerning the Slot-/Signal-architecture in Qt. For my project I have separate functions for:

a) GUI
b) controlling external devices

Now I want to have function b) constantly listening to Signals sent from a) on specific slots. But this listening should not influence the GUI thread, e.g. I want to continue with my work there.

Thus I had the idea to move the function b) to a separate thread. But my problem is that I do not know how to create the run-function in this thread. It should start with my program (no problem), and it should constantly listen to incoming signals and then run the function which is connected to this signal.

Would a simple while(1) be enough?

Upvotes: 4

Views: 441

Answers (1)

Jason C
Jason C

Reputation: 40335

Qt makes this pretty straightforward. I would not advise overriding run() for this as it is not necessary - also it is not as flexible or easy to implement, and has a few caveats regarding object creation.

Instead, just create a thread then move your listening object to it. For example:

// 'this' as parent means thread will terminate automatically when 'this'
// is deleted, you have other options here, of course.
QThread *thread = new QThread(this);

// Create your object (or just use an existing one). Note new object initially
// lives on current thread. Note also it does not have a parent. Objects with
// parents cannot be moved to other threads explicitly.
MyObject *object = new MyObject(); // Assuming MyObject is a QObject.

// Now move the object to the new thread.
object->moveToThread(thread);

// And, you'll want to make sure the object is deleted when the thread ends.
connect(thread, SIGNAL(finished()), object, SLOT(deleteLater()));
connect(thread, SIGNAL(terminated()), object, SLOT(deleteLater())); // just in case

// Finally, start the thread:
thread->start();

That's all you need to do! Now the thread is running, with its own event loop, and signals connected to the object's slots will be queued and run on that thread.

Note that if your object's constructor creates any QObjects of its own, it should set itself as those objects' parent accordingly. Qt will automatically move all child objects of your object to the thread as well when you do object->moveToThread().

You can move as many objects as you want to a given QThread, it isn't limited to just one.

To explicitly end the thread, and clean up the object, call thread->exit() or just delete the thread. Again, though, since we made this a parent of the QThread in the above example, you really don't need to do any cleanup at all.

By the way, if you have some initialization or other tasks that your object should perform on the thread when the thread is started, you can also use the thread's started() signal:

connect(thread, SIGNAL(started()), object, SLOT(initializeWhatever()));

Note, of course, that any objects used in the above way must be subclasses of QObject. This is where e.g. moveToThread() and deleteLater() are, and is also required for proper handling of slots:

class MyObject : public QObject {
    Q_OBJECT
public:
    MyObject (QObject *parent = 0);
signals:
    ...
public slots:
    ...
};

The easiest way, really, to set this up is in QtCreator, right click, add a new class, and choose QObject as a base there. Qt will set up a template header and source file for you.


Unless the connection type is DirectConnection, but by default it is not.

Upvotes: 3

Related Questions