简体   繁体   English

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

[英]Confusion regarding QThread, QObject, Thread Affinity and Event Loop

I was going through the links 我正在浏览链接

  1. You are doing it wrong 你做错了
  2. Using QThread in right way Part1 正确使用QThread Part1
  3. Using QThread in right way Part2 正确使用QThread Part2

I got confused by some statements. 我对一些陈述感到困惑。 In the first link, it says that 在第一个链接中,它说

all of the functions in QThread were written and intended to be called from the creating thread, not the thread that QThread starts. QThread中的所有函数都是编写的,并且打算从创建线程调用,而不是QThread启动的线程。

while it suggests to use moveToThread to move an object to new thread, instead of subclassing QThread . 虽然它建议使用moveToThread将对象移动到新线程,而不是子类化QThread My question is: 我的问题是:

The default implementation of run method calls exec , which creates an event loop , and when an object's thread affinity is changed using moveToThread , all the slots will be executed in the new thread , not on the creating thread , which is contradictory with the aforementioned intended use . run方法的默认实现调用exec ,它创建一个事件循环 ,当使用moveToThread更改对象的线程关联时 ,所有的slots都将在新线程中执行,而不是在创建线程上执行 ,这与上述预期相矛盾 Am I missing something? 我错过了什么吗?

Second question: 第二个问题:

In the third link it is said 据说第三个链接

event queue is belong to thread instead of event loop, and it's shared by all the event loops running in this thread. 事件队列属于线程而不是事件循环,并且由该线程中运行的所有事件循环共享。

My question is how there can be more than one event loop in a single thread ? 我的问题是如何在一个线程中有多个事件循环 What I understand is, event-loop loop through the event-queue , until exit / terminate is called, and processes each event arrives on that queue. 我理解的是, 事件循环遍历事件队列 ,直到调用exit / terminate ,并处理每个event到达该队列。 If this is true, one loop will never end (unless exit / terminate is called), how another can begin? 如果这是真的,一个循环将永远不会结束(除非调用exit / terminate ),另一个循环将如何开始? Any sample code demonstrating it will be highly appreciated. 任何展示它的示例代码都将受到高度赞赏。

"which is contradictory with the aforementioned intended use. Am I missing something?" “这与上述预期用途相矛盾。我错过了什么吗?”

Yes, I think you're misunderstanding the concept of thread affinity (the thread on which an object is running). 是的,我认为你误解了线程关联的概念(运行对象的线程)。

Let's take an example with minimal code: - 让我们以最少的代码为例: -

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

Assuming this code has been created from an object whose thread affinity is the main thread, such as QMainWindow , the thread object pThread is running on the main thread; 假设此代码是从一个对象创建的,该对象的线程亲和性是主线程,例如QMainWindow ,则线程对象pThread正在主线程上运行; it's thread affinity is the main thread. 它的线程亲和力是主线程。

In contrast, the QObject derived MyObject instance, myObj , has been moved to the new thread pThread . 相反, QObject派生的MyObject实例myObj已被移动到新线程pThread So, the thread affinity of myObj is now the new thread. 因此, myObj的线程亲和性现在是新线程。

The " functions written for QThread " are still called directly from the main thread, as that's where it's running. QThread编写的函数 ”仍然直接从主线程调用,因为它正在运行。

Think of QThread as a thread controller object, rather than the thread itself. QThread视为线程控制器对象,而不是线程本身。 This is one of the reasons why it is often discouraged to inherit from QThread , unless you want to change how QThread manages the underlying thread. 这是为什么经常不鼓励继承QThread的原因之一,除非你想改变QThread管理底层线程的方式。

how there can be more than one event loop in a single thread ?... 如何在一个线程中有多个事件循环?...

I've not used this directly myself, but I'll try to explain this as I understand it. 我自己并没有直接使用过这个,但我会按照我的理解来解释这个。 Perhaps someone else will be able to correct or confirm this. 也许其他人将能够纠正或确认这一点。 From the Qt Documentation for QEventLoop , it states: - QEventLoopQt文档中可以看出 : -

At any time, you can create a QEventLoop object and call exec() on it to start a local event loop. 您可以随时创建一个QEventLoop对象并在其上调用exec()以启动本地事件循环。

The signature from QEventLoop exec is: - 来自QEventLoop执行官的签名是: -

int QEventLoop::exec ( ProcessEventsFlags flags = AllEvents ) int QEventLoop :: exec(ProcessEventsFlags flags = AllEvents)

So if you pass in a set of flags, only these events would be handled. 因此,如果传入一组标志,则只处理这些事件。 Now, as calling exec() starts the processing of events until exit() is called, you can create a local event loop that lets your program wait until one or more specific events occur. 现在,当调用exec()开始处理事件直到调用exit() ,您可以创建一个本地事件循环,让程序等到一个或多个特定事件发生。

A second event loop is a local event loop within the main event loop, but as each event loop can process the whole event queue, which is shared by all event loops in a thread, it can be used to override event handling from the main event loop. 第二个事件循环是主事件循环中的本地事件循环,但是由于每个事件循环都可以处理整个事件队列(由线程中的所有事件循环共享),因此它可以用于覆盖主事件中的事件处理环。

If you conceptualise an event loop as doing something like this (pseudo code): - 如果您将事件循环概念化为执行此类操作(伪代码): -

QList<QEvent*> eventList;
while(!stop)
{
    // handle events in eventList
}

A 2nd event loop would then do this: - 然后第二个事件循环会这样做: -

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM