关于 QThread、QObject、线程亲和性和事件循环的混淆

Rak*_*kib 3 c++ qt qthread qobject qeventloop

我正在浏览链接

\n\n
    \n
  1. 你做错了
  2. \n
  3. 正确使用 QThread 第 1 部分
  4. \n
  5. 正确使用 QThread 第 2 部分
  6. \n
\n\n

我对一些说法感到困惑。在第一个链接中,它说

\n\n
\n

QThread 中的所有函数都是编写的,旨在从创建线程调用,而不是从 QThread 启动的线程调用。

\n
\n\n

虽然它建议使用moveToThread将对象移动到新线程,而不是子类化QThread。我的问题是:

\n\n

run方法调用的默认实现exec,会创建一个事件循环,当使用 改变对象的线程关联性moveToThread时,所有的操作slots都会在新线程中执行,而不是在创建线程上执行,这与前面提到的预期用途相矛盾相矛盾。我错过了什么吗?

\n\n

第二个问题:

\n\n

在第三个链接中说

\n\n
\n

事件队列属于线程而不是事件循环,并且它\xe2\x80\x99被该线程中运行的所有事件循环共享。

\n
\n\n

我的问题是单个线程中如何可以有多个事件循环?我的理解是,事件循环通过事件队列循环,直到exit/terminate被调用,并处理每个event到达该队列的事件。如果这是真的,一个循环将永远不会结束(除非 exit/terminate被调用),另一个循环如何开始?任何演示它的示例代码都将受到高度赞赏。

\n

The*_*ght 5

“这与上述预期用途相矛盾。我错过了什么吗?”

是的,我认为您误解了线程关联性(对象正在其上运行的线程)的概念。

让我们以最少的代码为例:-

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
Run Code Online (Sandbox Code Playgroud)

假设这段代码是从一个线程亲和性为主线程的对象创建的,例如QMainWindow,该线程对象pThread正在主线程上运行;它的线程亲和力是主线程。

相反,QObject派生MyObject实例myObj已移至新线程pThread。因此,线程亲和力myObj现在是新线程。

QThread”编写的函数仍然直接从主线程调用,因为主线程就是它运行的地方。

将其视为QThread线程控制器对象,而不是线程本身。这是通常不鼓励继承的原因之一QThread,除非您想更改QThread管理底层线程的方式。

一个线程中如何可以有多个事件循环?...

我自己没有直接使用过它,但我会尝试按照我的理解来解释它。也许其他人能够纠正或确认这一点。从Qt Documentation for QEventLoop中,它指出: -

您可以随时创建一个QEventLoop对象并调用exec()它来启动本地事件循环。

QEventLoop exec 的签名是: -

int QEventLoop::exec ( ProcessEventsFlags 标志 = AllEvents )

因此,如果您传入一组标志,则只会处理这些事件。现在,当调用exec()开始处理事件直到exit()被调用时,您可以创建一个本地事件循环,让您的程序等待一个或多个特定事件发生。

第二个事件循环是主事件循环中的本地事件循环,但由于每个事件循环可以处理整个事件队列,该队列由线程中的所有事件循环共享,因此它可以用于覆盖主事件中的事件处理环形。

如果您将事件循环概念化为执行类似的操作(伪代码):-

QList<QEvent*> eventList;
while(!stop)
{
    // handle events in eventList
}
Run Code Online (Sandbox Code Playgroud)

第二个事件循环将执行以下操作:-

bool bStop = false;
QList<QEvent*> eventList;
while(!bStop)
{
    // handle events in eventList
    ...
    ...
    // Inner event loop
    bool bStop = false;
    while(!bStop)
    {
        // handle events in eventList
    }
}
Run Code Online (Sandbox Code Playgroud)