在"moveToThread"之后,工作线程的插槽中未收到 PySide2 信号



在工人类被moveToThread之后,我在制作插槽接收信号时遇到了问题。目标是在另一个线程上执行工作线程中的槽。

这是我的测试工人班:

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的插槽能够从另一个线程执行。但其他插槽都没有这样做。此外,值得指出的是,只有在不进行调试的情况下运行此代码,才会打印最后一行。如果我在调试模式下运行,我会得到:

- 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

在最初的情况下(部分工作(,碰巧有时间创建线程,但由于函数立即终止,因此对象也被销毁。

最新更新