Путаница относительно QThread, QObject, Thread Affinity и Event Loop

Я просматривал ссылки

  1. Вы делаете это неправильно
  2. Использование QThread справа путь Часть 1
  3. Использование QThread справа путь Часть 2

Меня запутали некоторые утверждения. В первой ссылке написано, что

все функции в QThread были написаны и предназначены для вызова из создающего потока, а не из потока, который запускает QThread.

в то время как он предлагает использовать moveToThread для перемещения объекта в новый поток вместо создания подкласса QThread. У меня вопрос:

Реализация метода run по умолчанию вызывает exec, который создает цикл событий, и когда привязка потока объекта изменяется с помощью moveToThread, все slots будут выполняться в новая цепочка, а не в создаваемой цепочке, что противоречит вышеупомянутому предполагаемому использованию. Я что-то упускаю?

Второй вопрос:

В третьей ссылке сказано

очередь событий принадлежит потоку, а не циклу событий, и она используется всеми циклами событий, запущенными в этом потоке.

У меня вопрос: как может быть более одного цикла событий в одном потоке? Насколько я понимаю, цикл событий проходит через очередь событий, пока не будет вызван _7 _ / _ 8_, и обрабатывает каждый event, поступающий в эту очередь. Если это правда, один цикл никогда не закончится (если не будет вызван _10 _ / _ 11_), как может начаться другой? Мы будем очень признательны за любой образец кода, демонстрирующий это.


person Rakib    schedule 29.05.2014    source источник
comment
Вы пропустили Как действительно, действительно использовать QThreads; Полное объяснение: mayaposch.wordpress.com/2011/11/01/   -  person TheDarkKnight    schedule 29.05.2014
comment
@ Merlin069, изучал, но не упомянул, к моим вопросам это не относится.   -  person Rakib    schedule 29.05.2014
comment
Извините, тогда я не успел ответить.   -  person TheDarkKnight    schedule 29.05.2014
comment
Кто бы ни проголосовал против этого вопроса, объясните, почему.   -  person TheDarkKnight    schedule 29.05.2014
comment
Предлагается переместить в поток объекты кроме QThread. Таким образом, в новом потоке не выполняются QThread методы, кроме run.   -  person Kuba hasn't forgotten Monica    schedule 29.05.2014
comment
Именно так сказал Куба. Утверждение all of the functions in QThread were written and intended to be called from the creating thread, not the thread that QThread starts. в основном означает, что не делайте этого: moveToThread(this);.   -  person thuga    schedule 30.05.2014


Ответы (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 для 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
    }
}
person TheDarkKnight    schedule 29.05.2014
comment
Спасибо за ваш вклад. Пока остается первый вопрос, если я правильно понимаю, то статья противоречит сама себе. Но ваш ответ на второй вопрос был действительно полезен. +1 - person Rakib; 29.05.2014
comment
Не могли бы вы объяснить, в чем вы видите противоречие? Предполагаемое использование QThread состоит в том, что его функции вызываются из потока создания его объекта, тогда как функции объекта, перемещенного в этот поток, запускаются и вызываются в новом потоке. - person TheDarkKnight; 29.05.2014
comment
ваш последний комментарий действительно прояснил мое замешательство. - person Rakib; 30.05.2014