Qt: Правильный способ публикации событий в QThread?

В моем приложении Qt у меня есть основной поток и рабочий поток. Подклассы рабочего потока QThread и обрабатывают события через customEvent. Правильно ли это, чтобы основной поток отправлял события, обрабатываемые рабочим потоком?

QThread* myWorkerThread = // ...

QApplication::instance()->postEvent (myWorkerThread, new MyWorkRequestEvent(/* ... */);

Если я правильно прочитал документацию, он заявляет, что события обрабатываются в потоке объекта, которому принадлежит получатель события. Поскольку QThread был создан основным потоком, он принадлежит основному потоку - так будет ли это событие обрабатываться основным потоком (который был бы интуитивно понятным и в моем случае был бы неправильным)?

Ответ 1

Ваше понимание правильное и действительно очень неинтуитивное:)

Большая часть проблем связана с документацией для QThread, которая предлагает подклассу QThread. Хотя Qthread имеет собственный цикл событий, в цикле событий QThread будут обрабатываться только события и сигналы для QObjects, созданных в методе run() (созданных в этом потоке).

Гораздо лучше инкапсулировать логику потока в подкласс QObject, а затем переместить этот объект на экземпляр простого QThread. Затем вы можете связаться с этим QObject, используя сигналы (которые будут правильно поставлены в очередь по границам потока) или пользовательские события.

В этом подобном вопросе есть несколько ссылок, которые должны помочь.

Ответ 2

События обрабатываются главным циклом событий, который находится в QApplication или QCoreApplication. Поэтому нет смысла отправлять события в QObjects в других потоках (если вы не создаете еще один цикл событий, который я не уверен, возможно).

Вы можете отправлять события из других потоков в свой основной поток. myWorkerThread в вашем примере принадлежит основному потоку, потому что он создан там. Объекты, созданные вашим рабочим потоком в run() и ниже, принадлежат этому потоку.

Вы также можете отправлять сигналы в слоты в другом потоке, например, если вы хотите нарисовать виджет (который должен выполняться в основном потоке) из рабочего потока или аналогичного.