Python 3.x PyQt5+;Python3:将列表、dict作为信号参数跨线程传递
我使用pyqtSignal将python列表作为参数从工作线程发送到主线程。qt何时创建作为参数传递的对象的副本。根据:qt应该复制对象。但是,在下面的示例中,主线程可以更改从另一个线程发送的列表的内容Python 3.x PyQt5+;Python3:将列表、dict作为信号参数跨线程传递,python-3.x,multithreading,pyqt5,thread-safety,signals-slots,Python 3.x,Multithreading,Pyqt5,Thread Safety,Signals Slots,我使用pyqtSignal将python列表作为参数从工作线程发送到主线程。qt何时创建作为参数传递的对象的副本。根据:qt应该复制对象。但是,在下面的示例中,主线程可以更改从另一个线程发送的列表的内容 import sys import time from PyQt5.QtCore import QThread, QObject, pyqtSlot, pyqtSignal from PyQt5.QtWidgets import QApplication class ClassProcessi
import sys
import time
from PyQt5.QtCore import QThread, QObject, pyqtSlot, pyqtSignal
from PyQt5.QtWidgets import QApplication
class ClassProcessing(QObject):
py_sig_send_data = pyqtSignal(list)
def __init__(self):
super().__init__()
# initialize some variables
self.data = [1, 2, 3, 4, 5]
def worker(self):
print(self.data)
self.py_sig_send_data.emit(self.data)
time.sleep(1)
print("modfied data in thread", self.data)
class ClassProcessingThread(QObject):
def __init__(self):
super().__init__()
self.objThread = QThread()
self.objThread_id = 1
self.objThread_finished = False
self.processing = ClassProcessing()
self.processing.moveToThread(self.objThread)
self.objThread.started.connect(self.processing.worker)
self.objThread.start()
class SomeClass(QObject):
def __init__(self):
super().__init__()
@pyqtSlot(list)
def receive_data(self, data):
print("received data", data)
data[1] = 42
print("modified data", data)
def main():
app = QApplication(sys.argv)
processing_thread = ClassProcessingThread()
some_class = SomeClass()
processing_thread.processing.py_sig_send_data.
connect(some_class.receive_data)
sys.exit(app.exec_())
if __name__ == '__main__':
main()
输出:
[1, 2, 3, 4, 5]
received data [1, 2, 3, 4, 5]
modified data [1, 42, 3, 4, 5]
modified data in thread [1, 42, 3, 4, 5]
有人能给我解释一下如何以线程安全的方式通过pyqtSignal传递列表吗。谢谢。在使用信号在线程之间传递容器类型时,PyQt的行为与Qt不同 具体来说,没有自动转换[1]到等效的Qt类型,因此没有隐式复制。不过,PyQt确实提供了一种机制来显式请求此类转换。为此,您可以使用
QVariantList
或QVariantMap
定义自定义信号:
py_sig_send_data = pyqtSignal('QVariantList')
但是,需要注意的是,QVariantMap
仅支持字符串键
不过,总而言之,在通过线程间的信号传递可变python类型之前,明确地复制它们可能更简单、更清晰、更安全
[1] 或者至少,.有趣的是,没有更明确地说明这一点。我搜索了很多地方,但显然没有找到合适的地方。显式副本可能用于发送一次信号;复制到data_buffer和data_buffer的数据作为参数传递。连续发送(例如每秒50次)如何?发送线程和接收线程可能同时访问数据缓冲区。@John。如果你想避免复制,你就需要使用某种类型的。