Using signal/slot transfer data from sub thread to main thread,however,the applicaiton always crash!:(
-
Hi everyone,
I am creating an application that create a sub thread to setup data, then send the data to main thread to show by signal/slot, however, the application always crash, here is my code:
GUI.ui<?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>MainWindow</class> <widget class="QMainWindow" name="MainWindow"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>800</width> <height>600</height> </rect> </property> <property name="windowTitle"> <string>MainWindow</string> </property> <widget class="QWidget" name="centralwidget"> <widget class="QPushButton" name="btn_start_"> <property name="geometry"> <rect> <x>190</x> <y>40</y> <width>75</width> <height>23</height> </rect> </property> <property name="text"> <string>Start</string> </property> </widget> <widget class="QPushButton" name="btn_exit_"> <property name="geometry"> <rect> <x>310</x> <y>40</y> <width>75</width> <height>23</height> </rect> </property> <property name="text"> <string>Exit</string> </property> </widget> <widget class="QPlainTextEdit" name="plainTextEdit"> <property name="geometry"> <rect> <x>140</x> <y>90</y> <width>541</width> <height>351</height> </rect> </property> </widget> </widget> <widget class="QMenuBar" name="menubar"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>800</width> <height>23</height> </rect> </property> </widget> <widget class="QStatusBar" name="statusbar"/> </widget> <resources/> <connections/> </ui>
# -*- coding: utf-8 -*- ################################################################################ ## Form generated from reading UI file 'main_window.ui' ## ## Created by: Qt User Interface Compiler version 5.15.2 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ from PySide2.QtCore import * from PySide2.QtGui import * from PySide2.QtWidgets import * class Ui_MainWindow(object): def setupUi(self, MainWindow): if not MainWindow.objectName(): MainWindow.setObjectName(u"MainWindow") MainWindow.resize(800, 600) self.centralwidget = QWidget(MainWindow) self.centralwidget.setObjectName(u"centralwidget") self.btn_start_ = QPushButton(self.centralwidget) self.btn_start_.setObjectName(u"btn_start_") self.btn_start_.setGeometry(QRect(190, 40, 75, 23)) self.btn_exit_ = QPushButton(self.centralwidget) self.btn_exit_.setObjectName(u"btn_exit_") self.btn_exit_.setGeometry(QRect(310, 40, 75, 23)) self.plainTextEdit = QPlainTextEdit(self.centralwidget) self.plainTextEdit.setObjectName(u"plainTextEdit") self.plainTextEdit.setGeometry(QRect(140, 90, 541, 351)) MainWindow.setCentralWidget(self.centralwidget) self.menubar = QMenuBar(MainWindow) self.menubar.setObjectName(u"menubar") self.menubar.setGeometry(QRect(0, 0, 800, 23)) MainWindow.setMenuBar(self.menubar) self.statusbar = QStatusBar(MainWindow) self.statusbar.setObjectName(u"statusbar") MainWindow.setStatusBar(self.statusbar) self.retranslateUi(MainWindow) QMetaObject.connectSlotsByName(MainWindow) # setupUi def retranslateUi(self, MainWindow): MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None)) self.btn_start_.setText(QCoreApplication.translate("MainWindow", u"Start", None)) self.btn_exit_.setText(QCoreApplication.translate("MainWindow", u"Exit", None)) # retranslateUi
GUI frame inherited by GUI.py
# !/usr/bin/env python # encoding: utf-8 # @File : main_frame_module.py # @Time : 2021/6/16 # @Author : qz # @Version : 1.0 # @Email : weiweiqiao@126.com # @License : (C) Copyright 2013-2021 # @Brief : from PySide2.QtWidgets import QMainWindow from PySide2.QtCore import QThread from PySide2.QtCore import QObject from PySide2.QtWidgets import QApplication from PySide2.QtCore import Slot from PySide2.QtCore import Signal from pyside2_signal_slot_test.main_window import Ui_MainWindow from pyside2_signal_slot_test.manager import Manager from pyside2_signal_slot_test.data_module import Data class MainWin(QMainWindow): def __init__(self, parent = None): QMainWindow.__init__(self, parent) self.ui = Ui_MainWindow() self.ui.setupUi(self) self.__thread = QThread() self.__manager = Manager() self.__init_connect() def __init_connect(self): """ 链接信号槽 Returns: None """ # 点击退出程序按钮 self.ui.btn_exit_.clicked.connect(self.__exit_application) # 点击启动按钮 self.ui.btn_start_.clicked.connect(self.__do) self.si_send_do.connect(self.__manager.sl_slot) self.__manager.si_send_track.connect(self.__show_data) self.__manager.si_stop_sub_thread.connect(self.__sl_stop_sub_thread) def __start_thread(self, obj: QObject, thread: QThread): """ 启动子线程 Args: obj: 迁移入子线程中的对象 thread: 子线程 Returns: None """ if not thread.isRunning(): obj.moveToThread(thread) thread.start() @Slot() def __exit_application(self): QApplication.closeAllWindows() @Slot() def __do(self): self.__start_thread(self.__manager, self.__thread) self.si_send_do.emit() @Slot(Data) def __show_data(self, data: Data): """ 根据传入的数据在文本框中显示 Args: data: 传入的数据对象 Returns: None """ # 获取是否显示标识符 self.ui.plainTextEdit.appendPlainText(str(data.get_is_show())) @Slot(int) def __sl_stop_sub_thread(self, code: int): if 0 == code: self.__thread.exit() si_send_do = Signal()
# !/usr/bin/env python # encoding: utf-8 # @File : manager.py # @Time : 2021/6/16 # @Author : qz # @Version : 1.0 # @Email : weiweiqiao@126.com # @License : (C) Copyright 2013-2021 # @Brief : from PySide2.QtCore import QObject from PySide2.QtCore import Slot from PySide2.QtCore import Signal from pyside2_signal_slot_test.data_module import Data class Manager(QObject): def __init__(self): super().__init__() @Slot() def sl_slot(self): """ 生成数据对象,通过信号槽传递数据对象。退出当前线程(子线程) Returns: None """ # 生成数据对象 track = Data() track.setup_is_show(True) # 传递数据对象 self.si_send_track.emit(track) # 发射信号,退出子线程 self.si_stop_sub_thread.emit(0) # 传递Data类型数据 si_send_track = Signal(Data) # 结束子线程 si_stop_sub_thread = Signal(int)
# !/usr/bin/env python # encoding: utf-8 # @File : data_module.py # @Time : 2021/6/14 # @Author : qz # @Version : 1.0 # @Email : weiweiqiao@126.com # @License : (C) Copyright 2013-2021 # @Brief : from PySide2.QtCore import QObject class Data(QObject): def __init__(self): super(Data, self).__init__() # Dict instance self.__dict = {} self.__is_show = False self.__count = 0 def setup_data(self, key: str, value: str): """ 更新__dict的数据 Args: key: 关键字 value: 数据 Returns: None """ self.__dict.update(key, value) def get_dict(self): return self.__dict def setup_is_show(self, flag: bool): self.__is_show = flag def get_is_show(self): return self.__is_show
# !/usr/bin/env python # encoding: utf-8 # @File : main.py # @Time : 2021/6/16 # @Author : qz # @Version : 1.0 # @Email : weiweiqiao@126.com # @License : (C) Copyright 2013-2021 # @Brief : import sys from PySide2.QtWidgets import QApplication from pyside2_signal_slot_test.main_frame_module import MainWin if __name__ == '__main__': app = QApplication(sys.argv) form = MainWin() form.show() sys.exit(app.exec_())
The application is always crashing and show "Process finished with exit code -1073741819 (0xC0000005)"
-
Hi,
You should run your application through the debugger to see exactly where it crashes.
-
@SGaist
thx.
The crash only in "self.si_send_track.emit(track)" of "def sl_slot(self):" function in Manager.py after start sub thread in "self.__start_thread(self.__manager, self.__thread)" of "def __do(self):" function in GUI.py.
After comment "self.__start_thread(self.__manager, self.__thread)", the appliction is done well. -
What if you just print the parameter and nothing else in the slot ?
-
@SGaist
thx,I follow your mind.
I use None instead the parameter of TrackData. the application is well done, I print the instance of TrackData in "sl_slot" function of Manager class, the instance is not None. So I think custom type is the point :)
I have a question, Qt suggest that register custom type, it is useful in Pyside2? -
Did you try to run your application through gdb to learn where exactly it crashed ?