Qt 移动到线程(qApp->;thread())和信号插槽

Qt 移动到线程(qApp->;thread())和信号插槽,qt,signals-slots,Qt,Signals Slots,如果我理解正确,插槽将始终出现在主线程中。 那么,使用信号插槽系统和移动到线程(qApp->thread())之间有什么区别呢?您的理解是错误的 每个线程都有自己的事件队列,因此当发出信号时,如果连接已排队(不是直接连接),则会将其添加到与对象的线程关联性匹配的事件队列中 例如:- 假设我们有两个对象;在主线程上运行的object1和已移动到新线程的object2 connect(object1, &SomeObject::signal1, object2, &SomeOther

如果我理解正确,插槽将始终出现在主线程中。
那么,使用信号插槽系统和移动到线程(qApp->thread())之间有什么区别呢?

您的理解是错误的

每个线程都有自己的事件队列,因此当发出信号时,如果连接已排队(不是直接连接),则会将其添加到与对象的线程关联性匹配的事件队列中

例如:-

假设我们有两个对象;在主线程上运行的object1和已移动到新线程的object2

connect(object1, &SomeObject::signal1, object2, &SomeOtherObject::signal2);
当object1发出signal1时,一个事件被发布到新线程;将object2移动到的线程


当新线程处理其事件循环和signal1的事件时,它将执行object2的插槽signal2。这不在主线程上。

每个
QObject
树都可以分配给指定的线程
moveToThread
表示将对象树(对于给定的根对象)移动到该线程

Thread a,b,c;
a created b,  b created c;
connect(a, &QThread::finished, a, &QObject::deleteLater);
connect(b, &QThread::finished, b, &QObject::deleteLater);
connect(c, &QThread::finished, c, &QObject::deleteLater);
这并不意味着
QObject
的所有代码都分配给该线程。这意味着队列连接(不是直接连接)调用的任何插槽都将在给定线程中调用。仔细阅读和的文档

除了
Qt::DirectConnection
,所有连接都使用接收对象的拥有线程来传递信号。所有参数都被打包并发送到接收方的事件队列。当接收线程的事件循环获得控制权时,它将解压参数并调用插槽

请注意,我在上面写的是关于对象树的。如果对象具有父线程,则无法将其移动到其他线程。并且不能将对象重新租入属于不同线程的对象

默认情况下,对象被指定给创建它们的线程(如果它们没有父对象)。所以它不必是主线程

Thread a,b,c;
a created b,  b created c;
connect(a, &QThread::finished, a, &QObject::deleteLater);
connect(b, &QThread::finished, b, &QObject::deleteLater);
connect(c, &QThread::finished, c, &QObject::deleteLater);
我做了一些实验,发现如果b完成得比c快,c就不会被删除;但我们可以做到:
b->moveObject(a)//然后b将再次被删除。

非常感谢。我有两个问题:1。什么是“对象的线程关联”?在其中创建对象的线程?2.因此,如果我在一个工作线程中,并且我想更改gui,那么我需要从主线程进行更改。我只能使用moveToThread()函数?那么invokeMethod呢?线程关联是运行对象的线程。如果object2在主线程上启动,则它与该线程具有线程关联性。将其移动到thread2,则其线程关联为thread2。我想更改gui-这是什么意思?GUI必须(很少有例外)位于主线程上。invokeMethod是调用对象插槽的另一种方法,通常在不同的线程上,但不需要用信号连接对象。当我创建一个新的小部件时,我会遇到错误:小部件必须在gui线程中创建。在创建新的小部件之前,我尝试使用moveToThread(qApp->thread()),但仍然出现错误。然后我建议用代码示例开始一个新问题。您可以阅读如何创建一个好的示例