После обновления с PyQt 5.13.2 до PyQt 5.14.0 я наблюдал странное изменение поведения app.processEvents(QtCore.QEventLoop.WaitForMoreEvents)
в многопоточной среде.
Насколько я понимаю, если этот метод выполняется когда очередь событий пуста, она должна блокироваться до появления нового события и обрабатывать его. Однако иногда кажется, что метод помечает событие как «обработанное» без фактической его обработки.
Вот соответствующий код:
from PyQt5 import QtCore, QtWidgets
import time
class Thread(QtCore.QThread):
def __init__(self):
QtCore.QThread.__init__(self)
self.moveToThread(self)
self.var=False
self.set_var_signal.connect(self.set_variable,type=QtCore.Qt.QueuedConnection)
# setup simple signal and slot
set_var_signal=QtCore.pyqtSignal()
@QtCore.pyqtSlot()
def set_variable(self):
assert QtCore.QThread.currentThread() is self # make sure that it runs in the correct thread
print("Set variable")
self.var=True
def run(self):
assert QtCore.QThread.currentThread() is self # make sure that it runs in the correct thread
time.sleep(1.)
app.processEvents() # "clean up" all the sent events
print("First check:",self.var)
app.processEvents(QtCore.QEventLoop.WaitForMoreEvents) # here we wait for the signal event
print("Second check:",self.var)
app.processEvents() # "post-processing"; in principle, it should do nothing
print("Third check:",self.var)
app=QtWidgets.QApplication([])
th=Thread()
th.start()
time.sleep(2.) # wait until the thread is up and running
th.set_var_signal.emit()
time.sleep(3.) # wait to display the messages
Короче говоря, он создает отдельный поток с одна переменная и сигнал, который изменяет значение этой переменной. Этот поток ожидает, пока этот сигнал не будет получен и обработан, а затем печатает значение переменной. Я ожидаю, что результат будет
First check: False
Set variable
Second check: True
Third check: True
То есть изначально (после первого вызова processEvents
) переменная по-прежнему False
. После второго (блокирующего) вызова переменная устанавливается, и ее значение сообщается как True
. После третьего звонка ничего не меняется. Действительно, это то, что я наблюдаю с PyQt 5.13.2.
Однако после обновления до PyQt 5.14.0 результат меняется на
First check: False
Second check: False
Set variable
Third check: True
В этом случае, даже если второй вызов на processEvents
возвращает (что должно произойти только после обработки сигнала), состояние переменной все еще остается неизменным. Только после следующего вызова подключенный слот фактически выполняется. Более того, если в третьем («постобработка») вызове я также добавлю флаг QtCore.QEventLoop.WaitForMoreEvents
, результат превратится в
First check: False
Second check: False
Set variable
Т.е. этот последний вызов processEvents
заблокирован навсегда, даже если слот явно выполняется внутри этого вызова.
Это поведение меня сильно озадачивает, тем более что я не смог найти ничего релевантного в списке изменений между Qt 5.13 и 5.14 ( Новые функции в Qt 5.14 и Qt 5.14.0 Файлы изменений ). Что-то я не понимаю в связи между сигналами и событиями в PyQt? Я всегда предполагал, что сигналы подаются поверх событий, т. Е. Обработка события представляет собой выполнение соответствующего слота. Разве это не так?