QMutex 是否需要保护信号?
Do signals need to be protected by a QMutex?
我正在使用 PyQt5 和 2 个 QThreads 开发一个 GUI,它们将使用各自的信号加上一个用于将错误代码发送回 GUI 的共享信号。我知道 QThreads 是要与 pyqtSignals 一起使用的,但是除了你从两个不同的线程发出共享信号之外,它们的行为是否与信号有关?
此外,在共享信号上使用 Qmutex 是否会确保线程同时访问它,或者在处理信号时它是否无用?
我写了这个示例代码,它运行正常,但我不确定信号是如何处理的:
from PyQt5.QtCore import QObject, pyqtSignal, QThread, QCoreApplication
import time
import sys
class Class2(QThread):
def __init__(self, signal):
super().__init__()
self.signal2 = signal
def run(self):
self.signal2.emit("Class 2 signal emitted")
class Class1(QThread):
def __init__(self, signal):
super().__init__()
self.signal1 = signal
def run(self):
self.signal1.emit("Class 1 signal emitted")
class Action(QObject):
shared_signal = pyqtSignal(str)
def __init__(self):
super().__init__()
class1 = Class1(self.shared_signal)
class2 = Class2(self.shared_signal)
self.shared_signal.connect(self.action)
class1.start()
class2.start()
time.sleep(1)
def action(self, buffer):
print(buffer)
app = QCoreApplication([])
Action = Action()
sys.exit(app.exec_())
感谢您的帮助!
信号本身是线程安全的,因为它们的主要任务是对信息进行排队,为此使用了互斥体。
┌----------------------┐
| |
| QUEUE |
| |
└----------------------┘
▲ ▲ ... ▲ | | |
| | | ▼ ▼ ... ▼
SIGNALS SLOTS
连接可能不是线程安全的,因为它取决于连接的类型。我建议您阅读 the docs 以了解哪种连接是不安全的(例如,在不同线程上的 QObject 之间使用 Qt::DirectConnection
)。
在你的情况下,连接是安全的,另一方面,我认为 time.sleep 没有必要,但这会导致对象在调用信号之前被销毁,因此可能的解决方案是:
import sys
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QCoreApplication, QObject, QThread
class Class2(QThread):
def __init__(self, signal, parent=None):
super().__init__(parent)
self.signal2 = signal
def run(self):
self.signal2.emit("Class 2 signal emitted")
class Class1(QThread):
def __init__(self, signal, parent=None):
super().__init__(parent)
self.signal1 = signal
def run(self):
self.signal1.emit("Class 1 signal emitted")
class Action(QObject):
shared_signal = pyqtSignal(str)
def __init__(self):
super().__init__()
class1 = Class1(self.shared_signal, self)
class1.finished.connect(class1.deleteLater)
class2 = Class2(self.shared_signal, self)
class2.finished.connect(class2.deleteLater)
self.shared_signal.connect(self.action)
class1.start()
class2.start()
@pyqtSlot(str)
def action(self, buffer):
print(buffer)
def main():
app = QCoreApplication([])
action = Action()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
我正在使用 PyQt5 和 2 个 QThreads 开发一个 GUI,它们将使用各自的信号加上一个用于将错误代码发送回 GUI 的共享信号。我知道 QThreads 是要与 pyqtSignals 一起使用的,但是除了你从两个不同的线程发出共享信号之外,它们的行为是否与信号有关? 此外,在共享信号上使用 Qmutex 是否会确保线程同时访问它,或者在处理信号时它是否无用?
我写了这个示例代码,它运行正常,但我不确定信号是如何处理的:
from PyQt5.QtCore import QObject, pyqtSignal, QThread, QCoreApplication
import time
import sys
class Class2(QThread):
def __init__(self, signal):
super().__init__()
self.signal2 = signal
def run(self):
self.signal2.emit("Class 2 signal emitted")
class Class1(QThread):
def __init__(self, signal):
super().__init__()
self.signal1 = signal
def run(self):
self.signal1.emit("Class 1 signal emitted")
class Action(QObject):
shared_signal = pyqtSignal(str)
def __init__(self):
super().__init__()
class1 = Class1(self.shared_signal)
class2 = Class2(self.shared_signal)
self.shared_signal.connect(self.action)
class1.start()
class2.start()
time.sleep(1)
def action(self, buffer):
print(buffer)
app = QCoreApplication([])
Action = Action()
sys.exit(app.exec_())
感谢您的帮助!
信号本身是线程安全的,因为它们的主要任务是对信息进行排队,为此使用了互斥体。
┌----------------------┐
| |
| QUEUE |
| |
└----------------------┘
▲ ▲ ... ▲ | | |
| | | ▼ ▼ ... ▼
SIGNALS SLOTS
连接可能不是线程安全的,因为它取决于连接的类型。我建议您阅读 the docs 以了解哪种连接是不安全的(例如,在不同线程上的 QObject 之间使用 Qt::DirectConnection
)。
在你的情况下,连接是安全的,另一方面,我认为 time.sleep 没有必要,但这会导致对象在调用信号之前被销毁,因此可能的解决方案是:
import sys
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QCoreApplication, QObject, QThread
class Class2(QThread):
def __init__(self, signal, parent=None):
super().__init__(parent)
self.signal2 = signal
def run(self):
self.signal2.emit("Class 2 signal emitted")
class Class1(QThread):
def __init__(self, signal, parent=None):
super().__init__(parent)
self.signal1 = signal
def run(self):
self.signal1.emit("Class 1 signal emitted")
class Action(QObject):
shared_signal = pyqtSignal(str)
def __init__(self):
super().__init__()
class1 = Class1(self.shared_signal, self)
class1.finished.connect(class1.deleteLater)
class2 = Class2(self.shared_signal, self)
class2.finished.connect(class2.deleteLater)
self.shared_signal.connect(self.action)
class1.start()
class2.start()
@pyqtSlot(str)
def action(self, buffer):
print(buffer)
def main():
app = QCoreApplication([])
action = Action()
sys.exit(app.exec_())
if __name__ == "__main__":
main()