QPointer в многопоточных программах
Согласно http://doc.qt.io/qt-5/qpointer.html, QPointer очень полезен. Но я обнаружил, что это может быть неэффективно в следующем контексте:
Если я хочу показать этикетку три раза или сделать что-то еще, я должен использовать
if(label) label->show1();
if(label) label->show2();
if(label) label->show3();
вместоif(label) { label->show1();label->show2();label->show3(); }
только потому, что метка может быть уничтожена в другом потоке после label->show1();
или же label->show2();.
Есть ли красивый способ, кроме трех, если получить ту же функциональность?
Другой вопрос, когда метка уничтожается после того, как если (метка), является if(label) label->show1();
все еще не так?
У меня нет опыта в многопоточных программах. Любая помощь приветствуется.;)
2 ответа
Я думаю, что единственный безопасный способ сделать это - убедиться, что вы обращаетесь к своим QWidgets только из основного потока / потока GUI (то есть потока, в котором выполняется цикл обработки событий Qt, внутри QApplication::exec()).
Если у вас есть код, который выполняется в другом потоке, и этот код хочет, чтобы QLabels отображался / скрывался / что угодно, тогда этот код должен создать объект QEvent (или его подкласс) и вызвать qApp->postEvent() для отправить этот объект в основной поток. Затем, когда цикл событий Qt обнаруживает и обрабатывает это QEvent в главном потоке, это точка, в которой ваш код может безопасно выполнять действия с QLabels.
В качестве альтернативы (и, возможно, более просто), код вашего потока может излучать сигнал между потоками (как описано здесь) и позволяет Qt обрабатывать внутреннюю публикацию событий. Это может быть лучше для вашей цели.
Ни один из ваших подходов не является поточно-ориентированным. Возможно, что ваш первый поток выполнит if
заявление, то другой поток удалит ваш ярлык, и тогда вы будете внутри вашего if
заявление и сбой.
Qt предоставляет несколько конструкций синхронизации потоков, вы, вероятно, захотите начать с QMutex и узнать больше о безопасности потоков, прежде чем продолжить работу над этой программой.
Использование мьютекса сделает вашу функцию похожей на это:
mutex.lock();
label1->show();
label2->show();
label3->show();
mutex.unlock()
Пока ваш другой поток использует блокировку того же объекта мьютекса, он не сможет удалять ваши метки, пока вы их показываете.