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()
и ниже, принадлежат этому потоку.
Вы также можете отправлять сигналы в слоты в другом потоке, например, если вы хотите нарисовать виджет (который должен выполняться в основном потоке) из рабочего потока или аналогичного.