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()

Пока ваш другой поток использует блокировку того же объекта мьютекса, он не сможет удалять ваши метки, пока вы их показываете.

Другие вопросы по тегам