我正在尝试使用PyQt开发软件,但我常常遇到没有调试信息的软件崩溃(只有退出代码0xC0000409)。我使用的是QThread,我写了一个这样的系统:
class serialThreadC(QThread):
updateOutBox = QtCore.pyqtSignal(str)
updateStatus = QtCore.pyqtSignal(int)
def __init__(self):
super(serialThreadC, self).__init__()
self.ser = False
self.state = 0
self.serialEnabled = False
def run(self):
while True:
if self.state == -3 or self.state == -2:
if self.SerialEnabled:
self.updatePB(20)
elif self.state == 0:
if self.serialEnabled:
self.updatePB(20)
def ConnDisconn(self):
self.serialEnabled = not self.serialEnabled
def updatePB(self, stat):
self.state = stat
self.updateStatus.emit(self.state)
serialThread = serialThreadC()
serialThread.start()
## sw is a QDialog already loaded
serialThread.updateOutBox.connect(sw.updateOutBox)
serialThread.updateStatus.connect(sw.updateStatus)
sw.PB_ConnDisconn.clicked.connect(serialThread.ConnDisconn)
当我在serialEnabled
或run()
中读/写ConnDisconn()
时,我崩溃了。我知道PyQt不是线程安全的,并且错误的变量处理会导致我的类型崩溃,但我无法理解我的代码有什么问题。我的想法(可能是错的)是所有serialThread
方法都在同一个线程上执行,如果它们连接到gui(主线程)。那是错的吗?以同样的方式,我从serialThread
发出事件并将它们连接到GUI,但这从未给我带来任何问题。
你能看到我犯的错误吗?如果在没有其他信息的情况下发生崩溃,有没有办法调试代码? (我使用PyCharm 2017.1.3)。
答案 0 :(得分:2)
PyQt是线程安全的,与Qt是线程安全的程度相同。 Qt文档将告诉您其API的哪些部分可以保证如此,以及在什么情况下。
跨线程信号是线程安全的,因此在您的示例中调用updatePB
方法是可以的。你的ConnDisconn
方法不是线程安全的,但这与PyQt或Qt无关 - 它只是你编写它的结果。 serialEnabled
属性可以由两个线程同时读取/写入,因此行为严格未定义。编写这种线程安全的方法是使用mutex,如下所示:
class serialThreadC(QThread):
updateOutBox = QtCore.pyqtSignal(str)
updateStatus = QtCore.pyqtSignal(int)
def __init__(self):
super(serialThreadC, self).__init__()
self.ser = False
self.state = 0
self._mutex = QMutex()
self.serialEnabled = False
def ConnDisconn(self):
self._mutex.lock()
self.serialEnabled = not self.serialEnabled
self._mutex.unlock()
def run(self):
while True:
if self.state == -3 or self.state == -2:
self._mutex.lock()
if self.serialEnabled:
self.updatePB(20)
self._mutex.unlock()
elif self.state == 0:
self._mutex.lock()
if self.serialEnabled:
self.updatePB(20)
self._mutex.unlock()
(注意:如果您正在使用任何类型的IDE或调试器,并且您遇到意外错误或崩溃,那么诊断问题的第一步应该始终是在标准控制台中测试代码。 ,IDE或调试器本身可能是问题的原因,或者可能掩盖来自Python或底层库(如Qt)的错误消息。