假设对象obj
是否属于QThread T1
。理想情况下,具有Qhread T2
功能的obj
不能从T1
“拉”到T2
。 moveToThread()
文档中提到了这一点:
警告:此函数不是线程安全的;当前线程必须与当前线程亲和力相同。换句话说,此函数只能将对象从当前线程“推”到另一个线程,而不能将对象从任意线程“推”到当前线程。 但是,此规则有一个例外:没有线程亲缘关系的对象可以“拉”到当前线程。
此moveToThread()
的观点3暗示实际上是“撒谎的孩子”。因为answer将使对象可从其他线程移动。这是没有副作用的惯用方法吗?
moveToThread(nullptr)
附加问题:如果在第1行和第2行之间的void FunctionRunningInT2 (QObject& obj) // `obj` belongs to thread `T1`
{
obj.moveToThread(nullptr); // line-1 no event processing for obj!?
obj.moveToThread(T2); // line-2 is it OK ???
}
上发出了任何signal
,会发生什么?Rephrased:在obj
的情况下,以后不接收任何信号。但是,仍处理obj.disconnect()
之前的未决信号。 disconnect()
是否也正确?还是也会丢弃未决信号?
据我了解,一个人不能在另一个线程中的对象上调用moveToThread(nullptr)
。即使参数为moveToThread
,您也将收到来自Qt的以下消息:
nullptr
并且该对象不会从其线程中移动。
将对象拉到另一线程的安全方法是使用排队连接,即为可移动对象提供一个类似的插槽
QObject::moveToThread: Current thread ( ... ) is not the object's thread ( ... )
Cannot move to target thread (0x0)
这样,可以在mover对象中使用信号,例如
class Moveable : public QObject
{
Q_OBJECT
public:
Moveable() : QObject(nullptr) {}
public slots:
void moveMe(QThread * destination) { moveToThread(destination); }
连接他们
class Mover : public QObject
{
Q_OBJECT
signals:
void moveIt(QThread *);
以及任何需要的地方
connect(&mover, &Mover::moveIt, &moveable, &Moveable::moveMe, Qt::QueuedConnection);
或
mover.moveIt(QThread::currentThread());
[如果只是不想处理实现信号并连接它们,则可以安全地使用诸如:
mover.moveIt(to_whatever_thread);
再次利用排队的连接,但直接调用插槽。
关于附加问题。一旦将对象移动到线程QMetaObject::invokeMethod(&moveable, "moveMe", Qt::QueuedConnection, Q_ARG(QThread*, destination_thread));
,请按0x0
进行操作:
无法对该对象或其子对象进行任何事件处理,因为它们不再与任何线程关联。
因此,对象也将停止接收信号,甚至不会从也已移至here的另一个对象接收信号。