QThread 中创建的 QObject 丢失内部信号/槽连接
我有一个工作QThread
,其中创建了QObject
派生对象。该对象是其他两个 QObject
派生对象的聚合,因此存在用于信号链接并将两个内部对象绑定在一起的内部连接。
工作线程QThread
是QPlugin
的成员,因此在插件的整个生命周期中都存在。
我遇到的问题是,尽管该对象与应用程序的其余部分交互良好,但这些内部连接似乎已损坏。作为一个实验,我尝试在主线程中创建对象,并且内部连接正在运行,所以这肯定是我对 QThread 做错了。
我还尝试将对象移回主线程(诚然,在建立这些内部连接之后),但它没有效果。我循环浏览了内部连接的每种类型的连接(直接连接、队列连接等),但它要么没有效果,要么触发了死锁错误。通过连接传递的所有类型都已注册。
该对象是两个包含的对象的父 QObject,它不应该有什么区别,因为它们都驻留在同一个线程中,但我尝试将它们的父对象设置为 NULL 只是为了排除它 - 它不出所料没有效果。 QThread
不是任何事物的父级。
我唯一不确定的是该对象是从驻留在主线程中的工厂单例创建的,但从工作线程调用 - 那么它属于谁?我完全不知道我正在做什么(或没有做什么)来打破这些连接,所以非常感谢任何帮助。以下是应用程序相关部分的代码:
这是工作线程中的对象创建调用,对于上下文,该对象是来自 OBJ 导入器的多边形网格。
// Create mesh.
QString type = Sy::plugMeshType + "Sy_polyMesh";
QString name = proj->newNameIncrement( "objMesh" );
Sy::PluginArgs args; args << name;
Sy_polyMesh* obj = Sy_pluginLoader::createInstance< Sy_polyMesh >( type, args );
obj->mesh() = mesh;
obj->resizeBB();
result_ = obj;
// If in GUI mode, register it with the project.
if ( gui_ ) {
proj->registerSimObject( obj );
proj->selectObject( obj );
}
我的应用程序有一个相当广泛的插件架构,因此实际的线程启动代码被抽象为一个抽象工作类:
void Sy_abstractLongProcess::begin( Sy_abstractLongProcessWorker* worker )
{
worker_ = worker;
worker_->moveToThread( &thread_ );
QObject::connect( &thread_, SIGNAL( started() ), worker_, SLOT( work() ) );
QObject* thisObj = dynamic_cast< QObject* >( this );
QObject::connect( &thread_, SIGNAL( finished() ), worker_, SIGNAL( finished() ) );
QObject::connect( worker_, SIGNAL( finished() ), thisObj, SIGNAL( finished() ) );
QObject::connect( worker_, SIGNAL( progressChanged( double ) ), thisObj, SIGNAL( progressChanged( double ) ) );
QObject::connect( worker_, SIGNAL( finished() ), &thread_, SLOT( quit() ) );
thread_.start();
}
由于所有相关代码分布在许多类中,我不会列出所有内容(这个问题足够长),但如果您需要查看其他任何内容,请毫不犹豫地询问 - 我需要在这个问题上获得的所有帮助。
I have a worker QThread
in which a QObject
derived object is created. The object is an aggregate of two other QObject
derived objects, as such there are internal connections for signal linking and binding the two internal objects together.
The worker QThread
is a member of a QPlugin
, so is present throughout the lifetime of the plugin.
The problem I have is that although the object is interacting fine with the rest of the application, those internal connections seem to be broken. As an experiment I tried creating the object in the main thread and the internal connections are functioning, so it is definitely something I'm doing wrong with QThread
s.
I also tried moving the object back to the main thread (admittedly after those internal connections are made), but it had no effect. I cycled through every type of connection (Direct, Queued, etc) for the internal connections, but it either had no effect or triggered deadlock errors. All the types passed through the connections are registered.
The object is the parent QObject
of the two contained objects, it shouldn't make a difference as they all reside in the same thread, but I tried setting their parent to NULL just to rule it out - it had no effect unsurprisingly. The QThread
is not a parent to anything.
The only thing I am not certain of is that the object is created from a factory singleton that resides in the main thread, but is called from the worker thread - so who does it belong to? I am at a complete loss as to what I'm doing (or not doing) to break these connections, so any help is greatly appreciated. Here is the code at the relevant parts of the application:
This the object creation call in the worker thread, for context the object is poly mesh from an OBJ
importer.
// Create mesh.
QString type = Sy::plugMeshType + "Sy_polyMesh";
QString name = proj->newNameIncrement( "objMesh" );
Sy::PluginArgs args; args << name;
Sy_polyMesh* obj = Sy_pluginLoader::createInstance< Sy_polyMesh >( type, args );
obj->mesh() = mesh;
obj->resizeBB();
result_ = obj;
// If in GUI mode, register it with the project.
if ( gui_ ) {
proj->registerSimObject( obj );
proj->selectObject( obj );
}
I have quite an extensive plugin architecture to my app, so the actual thread starting code is abstracted into an abstract worker class:
void Sy_abstractLongProcess::begin( Sy_abstractLongProcessWorker* worker )
{
worker_ = worker;
worker_->moveToThread( &thread_ );
QObject::connect( &thread_, SIGNAL( started() ), worker_, SLOT( work() ) );
QObject* thisObj = dynamic_cast< QObject* >( this );
QObject::connect( &thread_, SIGNAL( finished() ), worker_, SIGNAL( finished() ) );
QObject::connect( worker_, SIGNAL( finished() ), thisObj, SIGNAL( finished() ) );
QObject::connect( worker_, SIGNAL( progressChanged( double ) ), thisObj, SIGNAL( progressChanged( double ) ) );
QObject::connect( worker_, SIGNAL( finished() ), &thread_, SLOT( quit() ) );
thread_.start();
}
As all the relevant code is spread across many classes, I won't list everything (this question is long enough), but if you need to see anything else don't hesitate to ask - I need all the help I can get on this one.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
当我尝试将对象移回主线程时,我几乎在原始帖子中找到了答案,只是我做得太早了。一旦完成需要在工作线程中完成的修改,我就必须将其移回原处 - 现在看起来很明显!
感谢 Mat 让我走上解决问题的正轨
I almost had the answer in the original post, when I tried to move the object back to the main thread, only I did it too early. I had to move it back once I completed the modifications that needed to be done in the worker thread - seems obvious now!
Thanks to Mat for putting me on track for working it out