在 `moveToThread` 之后,工人的槽中没有收到 PySide2 信号
PySide2 signals aren't received in slots of a worker after `moveToThread`
在工人 class moveToThread
之后,我无法让插槽接收信号。
目标是 worker 内部的槽将在另一个线程上执行。
这是我的测试人员class:
class DbWorker(QObject):
def __init__(self):
super().__init__()
logger.info(f"{threading.get_ident()}: DbWorker instantiated...")
@Slot(str)
def test_slot_str(self, test_text: str):
logger.info(f"{threading.get_ident()}: test_slot_str fired. Got Message '{test_text}'")
@Slot()
def test_slot_empty(self):
logger.info(f"{threading.get_ident()}: test_slot_empty fired ")
@Slot()
def process(self):
logger.info(f"{threading.get_ident()}: Process slot activated!")
当我执行这个时:
# Signals must inherit QObject
class Communicate(QObject):
signal_str = Signal(str)
signal_empty = Signal()
def moveToThreadTest():
logger.info(f"{threading.get_ident()}: main started...")
worker = DbWorker()
communicate = Communicate()
my_thread = QThread()
worker.moveToThread(my_thread)
communicate.signal_str.connect(worker.test_slot_str)
communicate.signal_empty.connect(worker.test_slot_empty)
my_thread.started.connect(worker.process)
my_thread.start()
communicate.signal_str.emit("test")
communicate.signal_empty.emit()
logger.info(f"{threading.get_ident()}: main thread end...")
我得到的输出是:
- INFO [db_worker.py:35 - moveToThreadTest() ] 13824: main started...
- INFO [db_worker.py:12 - __init__() ] 13824: DbWorker instantiated...
- INFO [db_worker.py:48 - moveToThreadTest() ] 13824: main thread end...
- INFO [db_worker.py:25 - process() ] 20776: Process slot activated!
所以连接到 my_thread.started
的插槽设法从另一个线程执行。但是 none o 其他插槽也是如此。此外,值得指出的是,只有当我 运行 这段代码没有调试时,才会打印最后一行。如果我 运行 在调试模式下,我得到这个:
- INFO [db_worker.py:35 - moveToThreadTest() ] 25128: main started...
- INFO [db_worker.py:12 - __init__() ] 25128: DbWorker instantiated...
- INFO [db_worker.py:48 - moveToThreadTest() ] 25128: main thread end...
我试着看看我是否以正确的方式将信号连接到插槽,所以我 运行 相同的示例没有将工作线程移动到线程,如下所示:
def withoutMoveToThread():
logger.info(f"{threading.get_ident()}: main started...")
communicate = Communicate()
worker = DbWorker()
communicate.signal_str.connect(worker.test_slot_str)
communicate.signal_empty.connect(worker.test_slot_empty)
communicate.signal_str.emit("Signal str")
communicate.signal_empty.emit()
logger.info(f"{threading.get_ident()}: main finished...")
它似乎运行良好:
- INFO [db_worker.py:52 - withoutMoveToThread() ] 6052: main started...
- INFO [db_worker.py:12 - __init__() ] 6052: DbWorker instantiated...
- INFO [db_worker.py:16 - test_slot_str() ] 6052: test_slot_str fired. Got Message 'Signal str'
- INFO [db_worker.py:20 - test_slot_empty() ] 6052: test_slot_empty fired
- INFO [db_worker.py:59 - withoutMoveToThread() ] 6052: main finished...
我不明白我做错了什么,为什么我的插槽没有收到连接的信号。请帮助我了解我做错了什么。
这是完整的示例文件:
import threading
from PySide2 import QtCore
from PySide2.QtCore import QObject, Slot, Signal, QThread
from logger import logger
class DbWorker(QObject):
def __init__(self):
super().__init__()
logger.info(f"{threading.get_ident()}: DbWorker instantiated...")
@Slot(str)
def test_slot_str(self, test_text: str):
logger.info(f"{threading.get_ident()}: test_slot_str fired. Got Message '{test_text}'")
@Slot()
def test_slot_empty(self):
logger.info(f"{threading.get_ident()}: test_slot_empty fired ")
@Slot()
def process(self):
# print("Process Activated!")
logger.info(f"{threading.get_ident()}: Process slot activated!")
# Signals must inherit QObject
class Communicate(QObject):
signal_str = Signal(str)
signal_empty = Signal()
def moveToThreadTest():
logger.info(f"{threading.get_ident()}: main started...")
worker = DbWorker()
communicate = Communicate()
my_thread = QThread()
worker.moveToThread(my_thread)
communicate.signal_str.connect(worker.test_slot_str)
communicate.signal_empty.connect(worker.test_slot_empty)
my_thread.started.connect(worker.process)
my_thread.start()
communicate.signal_str.emit("test")
communicate.signal_empty.emit()
logger.info(f"{threading.get_ident()}: main thread end...")
def withoutMoveToThread():
logger.info(f"{threading.get_ident()}: main started...")
communicate = Communicate()
worker = DbWorker()
communicate.signal_str.connect(worker.test_slot_str)
communicate.signal_empty.connect(worker.test_slot_empty)
communicate.signal_str.emit("Signal str")
communicate.signal_empty.emit()
logger.info(f"{threading.get_ident()}: main finished...")
if __name__ == '__main__':
withoutMoveToThread()
信号需要事件循环才能工作,在您的情况下,您必须创建一个 QCoreApplication:
def moveToThreadTest():
app = QCoreApplication.instance()
if app is None:
app = QCoreApplication()
logger.info(f"{threading.get_ident()}: main started...")
worker = DbWorker()
communicate = Communicate()
my_thread = QThread()
worker.moveToThread(my_thread)
communicate.signal_str.connect(worker.test_slot_str)
communicate.signal_empty.connect(worker.test_slot_empty)
my_thread.started.connect(worker.process)
my_thread.start()
communicate.signal_str.emit("test")
communicate.signal_empty.emit()
logger.info(f"{threading.get_ident()}: main thread end...")
app.exec_()
然后将 threading.get_ident()
更改为 threading.current_thread()
你会得到:
INFO:140406642902848: main started...
INFO:<_MainThread(MainThread, started 140406642902848)>: DbWorker instantiated...
INFO:140406642902848: main thread end...
INFO:<_DummyThread(Dummy-1, started daemon 140406565365312)>: Process slot activated!
INFO:<_DummyThread(Dummy-1, started daemon 140406565365312)>: test_slot_str fired. Got Message 'test'
INFO:<_DummyThread(Dummy-1, started daemon 140406565365312)>: test_slot_empty fire
在您的初始情况下(部分有效)碰巧有时间创建线程,但由于函数立即终止,因此对象也被销毁。
在工人 class moveToThread
之后,我无法让插槽接收信号。
目标是 worker 内部的槽将在另一个线程上执行。
这是我的测试人员class:
class DbWorker(QObject):
def __init__(self):
super().__init__()
logger.info(f"{threading.get_ident()}: DbWorker instantiated...")
@Slot(str)
def test_slot_str(self, test_text: str):
logger.info(f"{threading.get_ident()}: test_slot_str fired. Got Message '{test_text}'")
@Slot()
def test_slot_empty(self):
logger.info(f"{threading.get_ident()}: test_slot_empty fired ")
@Slot()
def process(self):
logger.info(f"{threading.get_ident()}: Process slot activated!")
当我执行这个时:
# Signals must inherit QObject
class Communicate(QObject):
signal_str = Signal(str)
signal_empty = Signal()
def moveToThreadTest():
logger.info(f"{threading.get_ident()}: main started...")
worker = DbWorker()
communicate = Communicate()
my_thread = QThread()
worker.moveToThread(my_thread)
communicate.signal_str.connect(worker.test_slot_str)
communicate.signal_empty.connect(worker.test_slot_empty)
my_thread.started.connect(worker.process)
my_thread.start()
communicate.signal_str.emit("test")
communicate.signal_empty.emit()
logger.info(f"{threading.get_ident()}: main thread end...")
我得到的输出是:
- INFO [db_worker.py:35 - moveToThreadTest() ] 13824: main started...
- INFO [db_worker.py:12 - __init__() ] 13824: DbWorker instantiated...
- INFO [db_worker.py:48 - moveToThreadTest() ] 13824: main thread end...
- INFO [db_worker.py:25 - process() ] 20776: Process slot activated!
所以连接到 my_thread.started
的插槽设法从另一个线程执行。但是 none o 其他插槽也是如此。此外,值得指出的是,只有当我 运行 这段代码没有调试时,才会打印最后一行。如果我 运行 在调试模式下,我得到这个:
- INFO [db_worker.py:35 - moveToThreadTest() ] 25128: main started...
- INFO [db_worker.py:12 - __init__() ] 25128: DbWorker instantiated...
- INFO [db_worker.py:48 - moveToThreadTest() ] 25128: main thread end...
我试着看看我是否以正确的方式将信号连接到插槽,所以我 运行 相同的示例没有将工作线程移动到线程,如下所示:
def withoutMoveToThread():
logger.info(f"{threading.get_ident()}: main started...")
communicate = Communicate()
worker = DbWorker()
communicate.signal_str.connect(worker.test_slot_str)
communicate.signal_empty.connect(worker.test_slot_empty)
communicate.signal_str.emit("Signal str")
communicate.signal_empty.emit()
logger.info(f"{threading.get_ident()}: main finished...")
它似乎运行良好:
- INFO [db_worker.py:52 - withoutMoveToThread() ] 6052: main started...
- INFO [db_worker.py:12 - __init__() ] 6052: DbWorker instantiated...
- INFO [db_worker.py:16 - test_slot_str() ] 6052: test_slot_str fired. Got Message 'Signal str'
- INFO [db_worker.py:20 - test_slot_empty() ] 6052: test_slot_empty fired
- INFO [db_worker.py:59 - withoutMoveToThread() ] 6052: main finished...
我不明白我做错了什么,为什么我的插槽没有收到连接的信号。请帮助我了解我做错了什么。
这是完整的示例文件:
import threading
from PySide2 import QtCore
from PySide2.QtCore import QObject, Slot, Signal, QThread
from logger import logger
class DbWorker(QObject):
def __init__(self):
super().__init__()
logger.info(f"{threading.get_ident()}: DbWorker instantiated...")
@Slot(str)
def test_slot_str(self, test_text: str):
logger.info(f"{threading.get_ident()}: test_slot_str fired. Got Message '{test_text}'")
@Slot()
def test_slot_empty(self):
logger.info(f"{threading.get_ident()}: test_slot_empty fired ")
@Slot()
def process(self):
# print("Process Activated!")
logger.info(f"{threading.get_ident()}: Process slot activated!")
# Signals must inherit QObject
class Communicate(QObject):
signal_str = Signal(str)
signal_empty = Signal()
def moveToThreadTest():
logger.info(f"{threading.get_ident()}: main started...")
worker = DbWorker()
communicate = Communicate()
my_thread = QThread()
worker.moveToThread(my_thread)
communicate.signal_str.connect(worker.test_slot_str)
communicate.signal_empty.connect(worker.test_slot_empty)
my_thread.started.connect(worker.process)
my_thread.start()
communicate.signal_str.emit("test")
communicate.signal_empty.emit()
logger.info(f"{threading.get_ident()}: main thread end...")
def withoutMoveToThread():
logger.info(f"{threading.get_ident()}: main started...")
communicate = Communicate()
worker = DbWorker()
communicate.signal_str.connect(worker.test_slot_str)
communicate.signal_empty.connect(worker.test_slot_empty)
communicate.signal_str.emit("Signal str")
communicate.signal_empty.emit()
logger.info(f"{threading.get_ident()}: main finished...")
if __name__ == '__main__':
withoutMoveToThread()
信号需要事件循环才能工作,在您的情况下,您必须创建一个 QCoreApplication:
def moveToThreadTest():
app = QCoreApplication.instance()
if app is None:
app = QCoreApplication()
logger.info(f"{threading.get_ident()}: main started...")
worker = DbWorker()
communicate = Communicate()
my_thread = QThread()
worker.moveToThread(my_thread)
communicate.signal_str.connect(worker.test_slot_str)
communicate.signal_empty.connect(worker.test_slot_empty)
my_thread.started.connect(worker.process)
my_thread.start()
communicate.signal_str.emit("test")
communicate.signal_empty.emit()
logger.info(f"{threading.get_ident()}: main thread end...")
app.exec_()
然后将 threading.get_ident()
更改为 threading.current_thread()
你会得到:
INFO:140406642902848: main started...
INFO:<_MainThread(MainThread, started 140406642902848)>: DbWorker instantiated...
INFO:140406642902848: main thread end...
INFO:<_DummyThread(Dummy-1, started daemon 140406565365312)>: Process slot activated!
INFO:<_DummyThread(Dummy-1, started daemon 140406565365312)>: test_slot_str fired. Got Message 'test'
INFO:<_DummyThread(Dummy-1, started daemon 140406565365312)>: test_slot_empty fire
在您的初始情况下(部分有效)碰巧有时间创建线程,但由于函数立即终止,因此对象也被销毁。