是否可以将对象实例移至QT项目中不同代码点的不同线程

Is it possible to move an object instance to different threads at different points of code in a QT project?

本文关键字:代码 线程 项目 QT 对象 实例 是否      更新时间:2023-10-16

我正在尝试确定在运行时是否可以将一个对象实例移至不同点的不同线程。

以下是一些示例代码,可以向您展示我的意思:

this->thread1           = new QThread( this );
this->thread2           = new QThread( this );
this->pObject->moveToThread( this->thread1 );
connect(this->thread1, SIGNAL(started()), this->pObject, SLOT(fnc1()));
connect(this->thread2, SIGNAL(started()), this->pObject, SLOT(fnc2()));
this->thread1->start();
//after thread1 has finished
this->pObject->moveToThread( this->thread2 );
this->thread2->start();

可以做到吗?

编辑:在Kuba关于不使用直接连接的建议之后,他指出我必须以某种方式干扰事件循环之后,我意识到手动终止线程不是一个好主意。我在此处添加了对线程的终止,以显示我出错的位置,并尝试找到一种更好的实现结果的方法。

connect(this->pObject, SIGNAL(finished()), this, SLOT(stopThread()));
void Class::stopThread( void )
{
    if( this->thread1->isRunning() )
    {
        this->thread1->terminate();
        return;
    }
    if( this->thread2->isRunning() )
    {
        this->thread2->terminate();
        this->pObject->moveToThread( this->thread1 );
    }
}
void Object::fnc1( void )
{
    /*Does some work..*/
    finished(); //Calls 'finished' to signal stopThread when done (not stopping on its own)
}

附加信息我有主流将实例保存到thread1,thread2和pobject(指向对象的指针我要从thread1转到thread2,并在必要时再次返回)。

主类构造函数:

MainClass::MainClass( QWidget *parent ) : QMainWindow(parent)
{
    this->ui.setupUi(this);
    this->thread1           = new QThread( this );
    this->thread2           = new QThread( this );
    this->pObject->moveToThread( this->thread1 );
    connect( this->pObject, SIGNAL(finished()), this, SLOT(stopThread()) );
    connect( this->thread1, SIGNAL(started()), this->pObject, SLOT(fnc1()) );
    connect( this->thread2, SIGNAL(started()), this->pObject, SLOT(fnc2()) );   
}

单击菜单项时的插槽:

void MainClass::on_action_call_fnc1_triggered( void )
{
    if( this->thread1->isRunning() )
        return;
    /*EXECUTES SOME CLASSIFIED CODE THAT CANNOT BE SHOWN*/
    this->thread1->start();//should trigger fnc1 execution
}

fnc1在thread1启动时称为对象类中的fnc1:

void Object::fnc1( void )
{
    /*DOES SOME MORE SECRET PROCESSING THAT CANNOT BE SHOWN*/
    this->finished(); // triggers MainClass::stopThread( void )
}

单击菜单项时的插槽开始执行FNC2:

void MainClass::on_action_call_fnc2_triggered( void )
{
    if( this->thread1->isRunning() || this->thread2->isRunning() )
        return;
    this->pObject->moveToThread( this->thread2 );
    this->thread2->start();//should trigger fnc2 execution
}

fnc2保存在对象中:

void Object::fnc2( void )
{
   /*DOES SOME MORE SECRET PROCESSING THAT CANNOT BE SHOWN*/
    this->finished(); // triggers MainClass::stopThread( void )
}

止损功能:

void MainClass::stopThread( void )
{
    if( this->thread1->isRunning() )
    {
        /*this->thread1->quit();
        this->thread1->exit();*/
        this->thread1->terminate();
        //this->thread1->wait( 0 ); //Trying different ways of stopping the thread
        return;
    }
    if( this->thread2->isRunning() )
    {
        this->thread2->terminate();
        //this->thread2->quit(); // Trying different ways of stopping the thread
        //this->thread2->exit();
        this->pObject->moveToThread( this->thread1 );
    }
}

它将起作用,但是您必须断言对象的线程确实已经完成:

Q_ASSERT(pObject->thread() == nullptr);
pObject->moveToThread(thread2);

thread1完成后,对象的线程变为null,只有这样,您才可以将其从任意线程移动到另一个线程。否则,如果对象的线程尚未完成,则只能将对象从其线程移动:

QTimer::singleShot(0, pObject, [this]{ pObject->moveToThread(thread2); }