如何编写监听传入信号的第二个线程

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

本文关键字:第二个 线程 信号 何编写 监听      更新时间:2023-10-16

我有一个关于Qt中Slot-/Signal架构的问题。对于我的项目,我有单独的功能:

a) GUI
b) 控制外部设备

现在我想让函数b)不断地监听从a)在特定插槽上发送的信号。但是这种监听不应该影响GUI线程,例如,我想继续我在那里的工作。

因此,我有了将函数b)移动到一个单独线程的想法。但我的问题是,我不知道如何在这个线程中创建run-函数。它应该从我的程序开始(没有问题),它应该不断地监听传入的信号,然后运行连接到这个信号的函数。

一个简单的while(1)就足够了吗?

Qt让这变得非常简单。我不建议为此重写run(),因为它没有必要——而且它也不那么灵活或易于实现,并且在对象创建方面有一些注意事项。

相反,只需创建一个线程,然后将侦听对象移动到它。例如:

// '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();

这就是你所需要做的!现在线程正在运行,它有自己的事件循环,连接到对象插槽的信号将排队并在该线程上运行

请注意,如果对象的构造函数创建了自己的任何QObject,那么它应该相应地将自己设置为这些对象的父对象。当您执行object->moveToThread()时,Qt也会自动将对象的所有子对象移动到线程中。

您可以将任意多个对象移动到给定的QThread,但不限于一个。

要显式结束线程并清理对象,请调用thread->exit()或删除线程。不过,由于我们在上面的示例中将this作为QThread的父级,所以实际上根本不需要进行任何清理。

顺便说一句,如果你有一些初始化或其他任务,当线程启动时,你的对象应该在线程上执行,你也可以使用线程的started()信号:

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

当然,请注意,以上述方式使用的任何对象都必须是QObject的子类。这是例如moveToThread()deleteLater()所在的位置,也是正确处理时隙所必需的:

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

实际上,最简单的设置方法是在QtCreator中,右键单击,添加一个新类,然后选择QObject作为基础。Qt将为您设置一个模板头和源文件。


除非连接类型为DirectConnection,但默认情况下不是。