将对象移至其他线程
moving an object to a different thread
我的应用程序使用自定义序列化机制。
阶段1 )机制将数据簇加载在单独的线程上,在那里创建所有适当的对象,等等。
阶段2 )一旦它们全部被完全挑选,它将它们交给主应用程序线程,并通过例如在对象之间设置连接等来完成序列化。
。 。这种机制是我框架的新补充 - 在此之前,我在主线程上都可以阐明所有内容。
我遇到的问题是,在deserializatiuon期间创建的某些对象是QT对象(基本上是一堆窗口小部件)。他们都记录了创建的线程的ID。当"第二阶段"的时间到来时,这些对象开始补充它们都不属于此线程,因此无法发送信号等。
因此,我在qobject上找到了一种方法,称为" movetothread"。但是,Little Bugger并不是很有帮助,因为它执行了检查并防止将对象从其他线程移动到当前线程(为什么要限制,我没有线索)。
有人知道我该怎么做?我可以保证这些对象只能在单独的线程上创建,从那时起,它们都将在主线程上生活和操作。
谢谢paksas
qObject的实例,或者在多线程中必须谨慎处理qobjects的任何实例。查看此页面以介绍该主题。
假设您的应用程序由两个线程 A 和 B 组成。假设线程a 创建对象qobject 实例。
实例 活作于线程a 。这意味着: - 它可以直接将信号发送给居住在线程A中的所有其他对象。 - 从线程A进行对Myinstance方法的所有调用均为线程安全
另一方面: - 不是线程安全的(您必须照顾种族条件)。 - 此外,由实例发出并连接到线程B中的对象插槽的信号不是直接的:通过复制所有方法参数并将所有方法放置在事件中执行的所有方法,将插槽执行推迟到以后的时刻。由线程B事件队列。
给出了这一点,您可以利用的解决方案是以下内容。
子类是qobject的子类。
class SubClass : public QObject{
Q_OBJECT
[...]
}
线程A将运行以下方法,以使用子类实例
进行填充内存void methodA(){ /this method is executed by thread A
QThread* threadB; //a reference to the QThread related to thread B
[...]
MyQObject* instance = someFactoryMethod();
//we push the ownership of instance from thrad A to thread B
instance->moveToThread( threadB );
//do something else
}
但是,如果线程A需要在实例上执行其他操作,这可能是不够的。特别是可能会触发MyQobject中定义的一些单曲。这是不允许的,因为现在线程A不再是实例的所有者。
在这种情况下,您需要推迟此操作并要求线程B执行。这是通过使用 QMETAOBJECT :: InvokeLater 方法来实现的。
InvokElater允许您调用特定的插槽,要求线程B执行它。
假设ClassInb是一类,其实例用于线程B
class ClassInB : public QObject{
Q_OBJECT
public:
[...]
slots:
void complexOperation(MyQObject* o){
[...]
emitSomeSignal();
}
signals:
void someSignal();
}
将实例移动到线程B后,我们需要在生活在螺纹B中的classinb的实例上执行 complectoperation(),这又会发出someSignal()。
void methodA(){ //this method is executed by thread A
QThread* threadB; //a reference to the QThread related to thread B
ClassInB* instanceOnB; //a reference to a ClassInB instance living in thread B
[...]
MyQObject* instance = someFactoryMethod();
//we push the ownership of instance from thread A to thread B
instance->moveToThread( threadB );
//we ask thread B to perform some operation related to instance
QMetaObject::invokeLater(instanceOnB, "complexOperation", Q_ARG(MyQObject*, instance) );
}
要能够将myqobject*用作 InvokElater 的参数,我们需要将其注册到Meta框架中。您需要:
- 在.cpp中添加
Q_DECLARE_METATYPE(MyQObject*)
定义myqobject - 在使用该机制之前一次致电(例如在主机中),
qRegisterMetaType<MyQObject*>();
只需用 QTimer::singleShot(int msec, const QObject *receiver, PointerToMemberFunction method)
替换函数调用即可在另一个线程中运行一个插槽,因为根据文档,它从目标线程执行插槽。
这样,您就不需要以任何方式打扰更改代码,或者想知道当前对象是否在同一线程中,等等。
- 当我在其中一个线程执行中(在activemq-cpp中)捕获到特定值时,我如何终止/停止所有其他线程
- MESI协议和std::atomic-它是否确保所有写入立即对其他线程可见?
- 锁定来自其他线程的类成员
- 使来自线程的数据流对所有其他线程都可读
- Qt信号和插槽如果从QRunnable或其他线程调用,则不起作用
- 当只有一个线程主要使用该对象而其他线程很少使用它时,如何最小化该对象的互斥锁锁定?
- 视频在唤醒其他线程时输入设备断开连接
- 如何从其他线程 winapi 获取消息
- 将抽象对象从主线程发送到其他线程
- 使用 std::condition_variable 触发其他线程.使用哪些互斥锁?
- 在其他线程中循环访问该concurrent_vector时调用 concurrency::concurrent_vect
- C++如何判断互斥体在阻塞其他线程时是否被单个线程不成比例地占用
- tbb::enumerable_thread_specific在其他线程库中工作吗
- 当其他线程正在编写线程安全时,我是否必须互斥读操作
- 无法从其他线程播放QMediaPlayer
- 无法修改其他线程中 ref 传递的值
- 其他线程堆栈上的可用内存无效
- Qt - 在其他线程上运行函数
- 在另一个 QThread 上运行成员方法时,无法将事件发送到其他线程拥有的对象
- SetWindowsHookEx 在挂接到其他线程时返回 NULL