关于 QThread、QObject、线程关联和事件循环的混淆
Posted
技术标签:
【中文标题】关于 QThread、QObject、线程关联和事件循环的混淆【英文标题】:Confusion regarding QThread, QObject, Thread Affinity and Event Loop 【发布时间】:2014-07-18 20:23:37 【问题描述】:我正在浏览链接
-
You are doing it wrong
Using QThread in right way Part1
Using QThread in right way Part2
我对一些陈述感到困惑。在第一个链接中,它说
QThread 中的所有函数都是编写并打算从创建线程调用,而不是从 QThread 启动的线程调用。
虽然它建议使用moveToThread
将对象移动到新线程,而不是继承QThread
。我的问题是:
run
方法的默认实现调用exec
,这会创建一个事件循环,并且当使用moveToThread
更改对象的线程亲和度 时,所有slots
将在新线程中执行,而不是在创建线程中执行,这与上述预期用途相矛盾。我错过了什么吗?
第二个问题:
在第三个链接中说
事件队列属于线程,而不是事件循环,它被运行在该线程中的所有事件循环共享。
我的问题是如何在一个线程中有多个事件循环?我的理解是,event-loop 循环通过 event-queue,直到调用 exit
/terminate
,并处理每个到达该队列的 event
.如果这是真的,一个循环将永远不会结束(除非exit
/terminate
被调用),另一个循环如何开始?任何演示它的示例代码都将受到高度赞赏。
【问题讨论】:
您错过了“如何真正、真正地使用 QThreads;完整说明”:mayaposch.wordpress.com/2011/11/01/… @Merlin069,我研究过,但没有提及,与我的问题无关。 对不起,我当时没时间回答。 谁否决了这个问题,请解释原因。 建议将QThread
以外的对象移至线程。因此,除了run
之外没有QThread
方法在新线程中执行。
【参考方案1】:
“这与上述预期用途相矛盾。我错过了什么吗?”
是的,我认为您误解了线程亲和性(对象正在运行的线程)的概念。
让我们以最少的代码为例:-
QThread* pThread = new QThread; // QThread on the main thread
MyObject* myObj = new MyObject; // MyObject on the main thread
myObj->moveToThread(pThread); // MyObject on the new thread, controlled by pThread
pThread->start(); // pThread instance is still on the main thread
假设这段代码是从一个线程亲和性为主线程的对象创建的,例如QMainWindow
,则线程对象pThread
在主线程上运行;它的线程亲和性是主线程。
相比之下,QObject
派生的MyObject
实例myObj
已移至新线程pThread
。所以,myObj
的线程亲和性现在是新线程。
“为QThread
编写的函数”仍然直接从主线程调用,因为它是在主线程运行的。
将QThread
视为线程控制器对象,而不是线程本身。这是通常不鼓励从QThread
继承的原因之一,除非您想更改QThread
管理底层线程的方式。
如何在一个线程中有多个事件循环?...
我自己并没有直接使用过这个,但我会尽量按照我的理解来解释。也许其他人将能够纠正或确认这一点。来自Qt Documentation for QEventLoop,它指出:-
您可以随时创建
QEventLoop
对象并在其上调用exec()
以启动本地事件循环。
来自 QEventLoop exec 的签名是:-
int QEventLoop::exec (ProcessEventsFlags flags = AllEvents)
因此,如果您传入一组标志,则只会处理这些事件。现在,调用exec()
开始处理事件,直到调用exit()
,您可以创建一个本地事件循环,让您的程序等待一个或多个特定事件发生。
第二个事件循环是主事件循环中的一个本地事件循环,但由于每个事件循环都可以处理整个事件队列,该队列由线程中的所有事件循环共享,它可以用来覆盖从主事件循环。
如果您将事件循环概念化为执行以下操作(伪代码):-
QList<QEvent*> eventList;
while(!stop)
// handle events in eventList
第二个事件循环会这样做:-
bool bStop = false;
QList<QEvent*> eventList;
while(!bStop)
// handle events in eventList
...
...
// Inner event loop
bool bStop = false;
while(!bStop)
// handle events in eventList
【讨论】:
感谢您的意见。如果我的理解是正确的,那么第一个问题仍然存在,而不是文章自相矛盾。但是您对第二个问题的回答确实很有帮助。 +1 你能解释一下你在哪里看到了矛盾吗? QThread 的预期用途是从创建对象的线程调用它的函数,而移动到该线程的对象的函数在新线程中运行和调用。 你最后的评论实际上澄清了我的困惑。以上是关于关于 QThread、QObject、线程关联和事件循环的混淆的主要内容,如果未能解决你的问题,请参考以下文章
重点:怎样正确的使用QThread类(注:包括推荐使用QThread线程的新方法QObject::moveToThread)