LINUX.ORG.RU

PySide2 и как завершить бесконечный цикл в потоке по сигналу?

 , , ,


0

1

И так Имеется гуй на пайсайде. В нём класс

class MyClass(QtCore.QObject):
    logs = QtCore.Signal(str)
    ...
    def run(self):
        self.logs.emit("Started")
        while(True):
            ...

который ясен пень выполняется в отдельном потоке.

while(True): строчка неправильная от слова совсем, должен быть while(anyState):.

Вот об anyState я и хочу спросить.

Как его менять по сигналу из вне для корректного завершения цикла? При этом не очень хочется наследоваться от главного гуишного потока. Есть реализация с таймером, но ситуация требует именно цикла.


UPD поток qthread, а не встроенный питунячий.



Последнее исправление: nikitalol (всего исправлений: 2)

Если в потоке не выполняется event loop то подход как праивло состоит в создании поля класса выполнябщего роль флага останова с потокобезопасным доступом. Принципиальных варианта два:

  • На Qt-сигналах можно объявить слот, и присоединить его к событию выдаваемомоу из другого потока через connect с параметром Qt.DirectConnection. В Qt-С++ при этом надо особо озаботиться потокобезопасностью, про PySide не знаю.
  • использовать чисто питоновское обращение к экземпляру класса без участия механизмов Qt. Тут тоже наверное какие-то грабли с синхронизацией могут быть, например если это обращение выполнится когда PySide находится в середине процесса разрушения объекта.
GPFault ★★
()
Ответ на: комментарий от GPFault

если это обращение выполнится когда PySide находится в середине процесса разрушения объекта.

Только если поток встал на io, иначе gil не пустит. Но в любом случае евент проще и безопаснее

upcFrost ★★★★★
()
Последнее исправление: upcFrost (всего исправлений: 1)
Ответ на: комментарий от upcFrost

насчёт threading.Event - весьма вероятно что вы правы, какой конкретный питоновский примитив тут подходит - я не знаю.

Но на первый взгляд важен способ обращения к нему из потока посылающего сигнал - видится что поток должен хранить сам should_stop_event, а не обращаться к нему как pyside_object.should_stop_event. Насколько я понимаю gil снимает не только io, а какой-нибудь питоновский callback.

Имею ввиду примерно следующую ситуацию:

  • начата разрушение PySide объекта (C++-деструкция по инициативе Qt).
  • по среди этого процесса PySide дёргает какой-нибудь питоновский callback - gil в это время не захвачен
  • питон переключается на другой поток и этот другой поток дёргает свойство/метод того же питоновсого объекта. Вполне возможно что PySide в какой-то версии у себя как-то переопределяет getattr/setattr. Тогда при таком дёргании эти методы будут вызваны. А вызывать методы у объекта в стадии деструкции - как правило плохая идея
GPFault ★★
()
Ответ на: комментарий от GPFault

А, понял, в плане что вызов пойдёт из питона к крестам, а не наоборот. С одной стороны да. С другой тот же Event можно использовать в нескольких местах, включая отправку команд в кресты. В конечном итоге все от реализации зависит.

Кстати автор внизу там добавил что это не питонячий поток, в этом случае я честно хз, опять же зависит от реализации

upcFrost ★★★★★
()
Ответ на: комментарий от steemandlinux

Это не баг.

И нет нуитки нет

По моему вы не очень поняли вопроса, но да с pyqt оно по моему воспроизводилось

nikitalol
() автор топика
Ответ на: комментарий от GPFault

На данный момент сделано так

class MyClass(QtCore.QObject):
    logs = QtCore.Signal(str)
    ...
    def __init__(self, obj):
        super().__init__()
        self.obj = obj

    def run(self):
        self.logs.emit("Started")
        while(self.obj.status):
            ...
# obj это класс с гуем

И это работает, но мне не нравится от слова совсем.

nikitalol
() автор топика
Ответ на: комментарий от upcFrost

Очень может быть. Может вообще выкину кутэшные потоки и сделаю на питоновских, тем более в MyClass кутэшных вещей кроме сигналов то нет

nikitalol
() автор топика
Ответ на: комментарий от nikitalol

Главное везде юзай одни и те же, иначе в какой-то момент можешь получить пачку интересных спецэффектов

upcFrost ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.