3

我正在浏览链接

  1. 你这样做是不对的
  2. 以正确的方式使用 QThread 第 1 部分
  3. 以正确的方式使用 QThread 第 2 部分

我被一些陈述弄糊涂了。在第一个链接中,它说

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

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

run方法调用的默认实现exec,它创建了一个事件循环,当一个对象的线程亲和性发生改变时moveToThread,所有的slots都将在新线程中执行,而不是在创建线程上,这与上述预期用途相矛盾。我错过了什么吗?

第二个问题:

在第三个链接中说

事件队列属于线程而不是事件循环,它被运行在该线程中的所有事件循环共享。

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

4

1 回答 1

4

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

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

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

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管理底层线程的方式。

一个线程中怎么会有多个事件循环?...

我自己并没有直接使用它,但我会尽力解释这一点。也许其他人将能够纠正或确认这一点。从QEventLoop 的 Qt 文档中,它指出: -

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

QEventLoop exec 的签名是:-

int QEventLoop::exec ( ProcessEventsFlags 标志 = 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
    }
}
于 2014-05-29T12:57:52.720 回答