正如this question中所建议的那样,我现在正试图融入多线程。
根据the links given by karlphillip,我理解不会遵循有关子类化QThread的文档,并按照说明使用moveToThread()
。现在我看到QThread run()
的默认实现只有一个exec()
,当工作线程完成操作时,必须通过调用quit()
来结束它。我现在有几个问题,以便我更好地理解事情:
QApplication* ptrApp=new QApplication(argc,argv);
QThread* th=new QThread;
MyClass* obj=new MyClass;
obj->moveToThread(th);
QObject::connect(th,SIGNAL(started()),obj,SLOT(someFunct()));
QObject::connect(obj,SIGNAL(over()),th,SLOT(quit()));
th->start();
//some GUI code in main thread here
return ptrApp->exec();
如果我在someFunct()
内发出over()
之后继续使用someFunct()
会怎样?这是不确定的行为还是正常的?
现在哪个线程会obj
与之关联(而over()
之后的其余代码仍在someFunct
中执行)?我的理解是:当我th
时,quit()
该线程... quit()
将排队,直到主线程中的exec()
执行它,这将导致exec()
run()
th
中的quit()
退出(我希望我在这里没有犯错误)。我认为该线程不再存在。
执行th
的插槽finished()
后,可以安全地假设该线程确实已退出,或者是否应进一步连接th
{{1}}信号到某个位置绝对确定?
答案 0 :(得分:1)
如果事件循环终止并不重要,somefunct()
将继续运行,直到它将控制权交还给现在已经灭绝的循环。
obj
保持与线程关联,因此如果发出连接到其中一个插槽的信号,则插槽将不会运行,但如果线程重新启动,它将排队等待。
如果QThread
对象被删除,obj->thread()
返回0,所以我认为这相当于调用obj->moveToThread(0)
并且根据文档:
如果targetThread为零,则此对象及其子对象的所有事件处理都将停止。
quit()
终止事件循环,然后从线程发出finished()
信号,线程终止。
因此,即使您收到finished()
信号,也不应该认为线程已经完成。在收到该信号后,您可以使用主线程中的QThread::wait
来确保这一点。
如果线程处于完成状态,QThread
析构函数已经调用wait
,那么您可以在finished()
信号后用deleteLater()
安全地删除该线程更安全)。
答案 1 :(得分:0)
1。如果我在someFunct()
内发出over()
之后继续使用someFunct()
会怎样?它是未定义的行为还是正常的?
当您使用直接连接时,发出over
将直接调用函数quit
,停止事件循环并从线程运行方法中的exec返回。这意味着someFunct()
将无法完成其执行,并且其中的对象要么丢失,要么处于部分修改状态。
2。 obj现在与哪个线程相关联(发出over()之后的其余代码仍在someFunct中执行)?
如前所述somefunct
将无法完成执行。但我相信与此线程相关的任何对象都将保持不变。我说我相信因为在任何地方都没有坚定的断言,但它最有意义。 As mentioned in the doc,要使这些对象发送或接收事件,必须再次启动线程....
3。一旦执行了插槽quit(),是否可以安全地假设线程确实已退出,或者我是否应该将th的完成()信号连接到某个插槽以确保绝对可靠?
quit()
终止事件循环并返回调用exec()
的位置。
请注意,对象Qthread不是线程。所以在你输入exec()
之前,它是正在运行的主线程......以及它是在exec
之后运行的主线程。
无论如何,这些都是一些很棒的问题......