iam*_*ind 5 c++ qt multithreading idioms qobject
假设一个对象是否obj属于QThread T1. 理想情况下,在Qhread T2's 函数中,obj不能从T1to '拉' T2。这在moveToThread()文档中提到:
警告:此函数不是线程安全的;当前线程必须与当前线程关联相同。换句话说,这个函数只能将一个对象从当前线程“推”到另一个线程,它不能从任意线程“拉”一个对象到当前线程。但是,此规则有一个例外:没有线程关联的对象可以“拉”到当前线程。
这个答案的第 3 点表明它实际上是一个“对孩子的谎言”。因为moveToThread(nullptr)将使一个对象可以从其他线程移动。
这是一种没有副作用的惯用方法吗?
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 ???
}
Run Code Online (Sandbox Code Playgroud)
附加问题:如果在第 1 行和第 2 行之间signal发出任何信号,会发生什么obj?
改写:在 的情况下obj.disconnect(),它之后不接受任何信号。但是,之前未决的信号disconnect()仍在处理中。这是真的了moveToThread(nullptr)呢?或者它也会丢弃待处理的信号?
据我了解,人们无法调用moveToThread位于不同线程中的对象。即使参数是nullptr,您最终也会收到来自 Qt 的以下消息:
Run Code Online (Sandbox Code Playgroud)QObject::moveToThread: Current thread ( ... ) is not the object's thread ( ... ) Cannot move to target thread (0x0)
并且该对象不会从其线程中移动。
将对象拉到不同线程的一种安全方法是使用排队连接,即为可移动对象提供一个插槽,例如
class Moveable : public QObject
{
Q_OBJECT
public:
Moveable() : QObject(nullptr) {}
public slots:
void moveMe(QThread * destination) { moveToThread(destination); }
Run Code Online (Sandbox Code Playgroud)
这样,人们就可以在移动对象中使用信号,例如
class Mover : public QObject
{
Q_OBJECT
signals:
void moveIt(QThread *);
Run Code Online (Sandbox Code Playgroud)
连接它们
connect(&mover, &Mover::moveIt, &moveable, &Moveable::moveMe, Qt::QueuedConnection);
Run Code Online (Sandbox Code Playgroud)
并且,在任何需要的地方
mover.moveIt(QThread::currentThread());
Run Code Online (Sandbox Code Playgroud)
或者
mover.moveIt(to_whatever_thread);
Run Code Online (Sandbox Code Playgroud)
如果只是不想处理实现信号并连接它们,可以安全地使用类似的东西:
QMetaObject::invokeMethod(&moveable, "moveMe", Qt::QueuedConnection, Q_ARG(QThread*, destination_thread));
Run Code Online (Sandbox Code Playgroud)
再次利用排队连接,但直接调用槽。
关于附加问题。一旦对象被移动到线程0x0,如下所述:
该对象或其子对象不会发生任何事件处理,因为它们不再与任何线程关联。
因此,该对象也将停止接收信号,即使是来自也已移动到 的另一个对象的信号0x0。
| 归档时间: |
|
| 查看次数: |
394 次 |
| 最近记录: |