2011-09-28 2 views
2

Согласно http://doc.qt.io/qt-5/qpointer.html, QPointer очень полезен. Но я нашел, что это может оказаться неэффективным в следующем контексте:QPointer в многопоточных программах

Если я хочу показать этикетку три раза или сделать что-то еще, я должен использовать

if(label) label->show1(); if(label) label->show2(); if(label) label->show3();

вместо if(label) { label->show1();label->show2();label->show3(); }

только потому, что ярлык может быть разрушен в другой теме после label->show1(); o r label->show2();.

Есть ли отличный способ, кроме трех, если бы получить такую ​​же функциональность?

Другой вопрос: когда этикетка уничтожается после if (label), то if(label) label->show1(); все еще не так?

У меня нет опыта в многопоточных программах. Любая помощь приветствуется. ;)

+4

ярлык может быть разрушен между if (label) и label-> show1(). –

ответ

6

Я думаю, что единственный безопасный способ сделать это - убедиться, что вы только получаете доступ к своим QWidgets из потока основного/графического интерфейса (то есть потока, который запускает цикл событий Qt, внутри QApplication :: exec()) ,

Если у вас есть код, который работает в другом потоке, и этот код хочет, чтобы QLabels отображались/скрыты/что угодно, тогда этому коду необходимо создать объект QEvent (или его подкласс) и вызвать qApp-> postEvent(), чтобы отправить этот объект в основной поток. Затем, когда цикл событий Qt захватывает и обрабатывает этот QEvent в основном потоке, это тот момент, когда ваш код может безопасно делать что-то с QLabels.

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

0

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

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

Использование мьютекса сделает вашу функцию будет выглядеть примерно так:

mutex.lock(); 
label1->show(); 
label2->show(); 
label3->show(); 
mutex.unlock() 

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

+1

Правило AFAIK Qt - «не касаться объектов GUI из потоков, отличных от основного потока». В частности, я не уверен, что события, помещающие блокировку мьютекса вокруг вышеупомянутых вызовов, будут достаточными, поскольку нет гарантии, что основной поток Qt не имеет доступа к этим QLabels (через их родительский виджет), например. для перерисовки, и Qt не будет знать, чтобы заблокировать мьютекс. –

Смежные вопросы