QObject, созданный в QThread, теряет внутренние соединения сигнала/слота

У меня есть рабочий QThread, в котором создается производный объект QObject. Объект представляет собой совокупность двух других QObject производных объектов, поэтому существуют внутренние соединения для связывания сигналов и связывания двух внутренних объектов вместе.

Рабочий QThread является членом QPlugin, поэтому присутствует на протяжении всего времени существования плагина.

У меня проблема в том, что хотя объект нормально взаимодействует с остальной частью приложения, эти внутренние соединения, похоже, разорваны. В качестве эксперимента я попытался создать объект в основном потоке, и внутренние соединения работают, так что это определенно что-то, что я делаю неправильно с QThreads.

Я также попытался переместить объект обратно в основной поток (правда, после того, как эти внутренние соединения были выполнены), но это не дало никакого эффекта. Я перебирал все типы соединений (прямые, очереди и т. д.) для внутренних соединений, но это либо не имело никакого эффекта, либо вызывало ошибки взаимной блокировки. Все типы, проходящие через соединения, регистрируются.

Объект является родителем 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();
}

Поскольку весь соответствующий код разбросан по многим классам, я не буду перечислять все (этот вопрос достаточно длинный), но если вам нужно увидеть что-то еще, не стесняйтесь спрашивать - мне нужно все помощь, которую я могу получить на этом.


person cmannett85    schedule 27.11.2011    source источник
comment
Попробуйте воспроизвести вашу проблему в намного более простой конфигурации (два объекта, два потока, один сигнал/слот). Здесь происходит слишком много всего, о чем мы не знаем. (И этот dynamic_cast не обнадеживает с точки зрения сложности вашей иерархии классов.)   -  person Mat    schedule 27.11.2011
comment
Хороший звонок, я постараюсь собрать что-нибудь вместе. Хотя с dynamic_cast все в порядке, эти соединения выполняются без проблем.   -  person cmannett85    schedule 27.11.2011


Ответы (1)


У меня почти был ответ в исходном посте, когда я попытался переместить объект обратно в основной поток, только я сделал это слишком рано. Мне пришлось переместить его обратно после того, как я завершил изменения, которые необходимо было сделать в рабочем потоке - теперь это кажется очевидным!

Спасибо Мэту за то, что он помог мне разобраться

person cmannett85    schedule 27.11.2011