关于QThread,QObject,线程亲和力和事件循环的困惑

时间:2014-05-29 10:43:34

标签: c++ qt qthread qobject qeventloop

我正在浏览链接

  1. You are doing it wrong
  2. Using QThread in right way Part1
  3. Using QThread in right way Part2
  4. 我对一些陈述感到困惑。在第一个链接中,它表示

      

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

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

    run方法的默认实现调用exec,创建事件循环,以及对象的线程关联使用moveToThread进行更改,所有slots都将在新主题中执行,而不是在创建主题中执行,这与上述内容相矛盾预期用途。我错过了什么吗?

    第二个问题:

    在第三个链接中说

      

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

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

1 个答案:

答案 0 :(得分: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管理底层线程的方式。

  

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

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

  

您可以随时创建QEventLoop对象并在其上调用exec()以启动本地事件循环。

QEventLoop执行官的签名是: -

  

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
    }
}