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)
_
run()
またはConnDisconn()
でserialEnabled
を読み書きすると、クラッシュします。 PyQtはスレッドセーフではなく、変数の処理を誤ると私の型がクラッシュすることは知っていますが、コードの何が問題なのか理解できません。私の考え(おそらく間違っている)は、すべてのserialThread
メソッドが、GUI(メインスレッド)に接続されている場合でも、同じスレッドで実行されるというものです。それは間違っていますか?同様に、serialThread
からイベントを発行し、それらをGUIに接続しましたが、問題が発生することはありませんでした。
私が犯した間違いがわかりますか?他の情報なしでクラッシュした場合にコードをデバッグする方法はありますか? (私はPyCharm 2017.1.3を使用しています)。
PyQtは、Qtがスレッドセーフであるのと同じ程度にスレッドセーフです。 Qtのドキュメントでは、APIのどの部分がそうなることが保証されているか、どのような状況であるかがわかります。
クロススレッドシグナルはスレッドセーフであるため、例のupdatePB
メソッドを呼び出しても問題ありません。あなたのConnDisconn
メソッドはスレッドセーフではありませんが、それはPyQtやQtとは何の関係もありません-それはあなたがそれをどのように書いたかの結果です。 serialEnabled
属性は、2つのスレッドによって同時に読み取り/書き込みが可能であるため、動作は厳密に定義されていません。これを書くスレッドセーフな方法は、次のように 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など)。