您可以通过向工人类添加新属性来完成此任务。只需确保它不会遮蔽对象中的任何其他属性、方法、槽或信号即可。这样,您现在可以通过参数区域从初始化将数据传递到线程:
class Worker(QObject):
finished = pyqtSignal()
def __init__(self, text="Foo"):
QObject.__init__(self)
self.firstNameText = text
On your 主线程,当您创建工作对象时,您可以使用我们刚刚设置的参数放置传递数据:
# On Main Thread
wk = Worker("Hello World")
wk.moveToThread(...)
现在,当我们打印firstNameText
上的变量其他线程,它将打印:Hello World
.
但是,如果您需要在线程已经运行时将数据传递给该线程,那就是另一回事了:我们必须考虑线程安全 and 同步。让我们使用firstNameText
变量为例。想象一下它从字符串开始设置Foo
:
- 如果在期间怎么办主线程,我们决定将该值更改为
Oof
同时,从其他线程?哪个值将其他线程打印?我们无法确定,要么是Foo
or Oof
.
- 如果在期间怎么办主线程,我们决定将该值更改为
Oof
同时,其他线程尝试将该值更改为ABC
然后打印它。将打印哪个值其他线程?再说一遍,我们不能确定,要么是Oof
or ABC
.
如果您仍然对此示例感到困惑,请阅读有关如何多线程 or 多重处理 works.
为了防止这个问题,我们必须使用互斥体来同步对firstNameText
两个线程之间的变量。幸运的是,Qt 已经提供了QMutex
类,所以让我们使用它。
当我们创建线程时主线程,我们必须分享QMutex
:
# ...
mt = QMutex()
th = QThread()
wk = Worker()
wk._mutex = mt
wk.moveToThread(th)
# ...
如果您想在任何情况下修改此变量其他线程或在主线程到另一个值,例如:wk._mutex = None
,如果两个线程仍然同时运行,这就会出现问题。您没有对该变量的独占访问权限,所以要小心。当您知道只有 1 个线程访问此属性时,只需在没有任何互斥体的情况下执行此操作即可。
但是如果两个线程都到达只读 the Worker._mutex
属性,无论是加锁还是解锁,我们都不需要再担心线程安全的问题了。属性的状态永远不会改变,所以无论是否主线程 or the 其他线程正在访问它时,worker 的实例仍将存在,并由该属性存储。
现在,当我们想要传递一个值时主线程侧 to the 其他线程,我们可以简单地写:
# On main thread:
wk._mutex.lock()
wk.firstNameText = myInput.text()
wk._mutex_unlock()
# On the other thread:
self._mutex.lock()
text = self.firstNameText
self._mutex.unlock()
里面的一切lock
and unlock
锁定这些锁的线程之间的调用是线程安全的。如果你永不解锁锁定的锁,尝试再次锁定它的其他线程将卡在该函数调用上,因此使用它们时要非常小心。永远不要忘记解锁它们。
为了保持简单易用,我们可以将所有这些都放在两个单独的方法中,一个setter and a getter:
class Worker(QObject):
finished = pyqtSignal()
def __init__(self):
QObject.__init__(self)
self.firstNameText = ""
self._mutex = QMutex()
def getFirstName(self):
self._mutex.lock()
text = self.firstNameText
self._mutex.unlock()
return text
def setFirstName(self, text):
self._mutex.lock()
self.firstNameText = text
self._mutex.unlock()
def run(self):
firstname = self.getFirstName()
for i in range(10):
sleep(1)
print(firstname)
self.finished.emit()
并从你的主线程,您可以随时致电:
wk.setFirstName("Hello World 2")
If the 其他线程仍在运行,这就是将在终端上打印的值。