Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用线程回调时Python解释器崩溃_Python_Multithreading_Callback_Crash_Pyqt5 - Fatal编程技术网

使用线程回调时Python解释器崩溃

使用线程回调时Python解释器崩溃,python,multithreading,callback,crash,pyqt5,Python,Multithreading,Callback,Crash,Pyqt5,我已经用pyqt5编写了一个Gui应用程序 我使用threading.Thread创建一个线程,它执行一些计算。 该线程获取name、target、args、kwargs和作为我的应用程序类成员的回调函数 除了最后一次运行外,回调会运行几次。 例如,100次呼叫中的前99次做得很好,但第100次导致错误。 在上次从回调返回后,解释器在大约一秒钟后崩溃,出现Windows事件,事件代码为0xc0000005 回调也有**KWARG作为参数 python本身没有任何回溯 有人知道是什么原因或我做错了

我已经用pyqt5编写了一个Gui应用程序

我使用threading.Thread创建一个线程,它执行一些计算。 该线程获取name、target、args、kwargs和作为我的应用程序类成员的回调函数

除了最后一次运行外,回调会运行几次。 例如,100次呼叫中的前99次做得很好,但第100次导致错误。 在上次从回调返回后,解释器在大约一秒钟后崩溃,出现Windows事件,事件代码为0xc0000005

回调也有**KWARG作为参数

python本身没有任何回溯

有人知道是什么原因或我做错了什么吗

环境:

  • 视窗10
  • Python 3.9.0
  • PyQt5.15.1
这两个类的一个最小示例(可能不起作用):

最后一次使用最后一个文件调用_func_callback时会产生以下输出:

已输入回调 __更新用户界面:调用回调! 更新GUI已完成 返回值:1 睡眠时间:0 睡眠时间:1

睡后:1 python解释器崩溃。

我可以自己解决: 随着设计的改变,问题消失了

问题是使用非新gui线程函数回调gui类(在gui线程中)。 在使用信号而不是回调之后,它工作得很好

结论: 切勿从非gui线程函数调用gui线程函数。

请提供
from Controller.filecontroller import Files_Controller as filecontroller

class DialogBatch(QDialog): 
    
    def __init__(self, parent= None):

        #    Initialize super-class
        super(DialogBatch, self).__init__()
        #    Load the GUI Description File, created with QtDesigner
        uic.loadUi('.\\GUI_dialog_batch_ui\\dialog_batch.ui', self)
        
        #    QProgressBars
        self.progressBar_batch_progress = self.findChild(QProgressBar, 'progressBar_batch_progress')
        
        #    QPushButtons
        self.pushButton_batch_start = self.findChild(QPushButton, 'pushButton_batch_start')
        
        ....  

        #    Filecontroller for file-operations
        self.filecontroller = filecontroller()
        
        #    Thread for executing high-level batch operations; 
        self.__batchthread = None

        #    Show GUI
        self.show()

    ....
    # Callback
    def __update_GUI(self, **kwargs):
        """!    Hidden method for updating the GUI
        @param key-only progress: [int] progress of the task executed
        @return: [int]    1 after finishing
        """
        test = deepcopy(kwargs)
        
        print("Callback entered")

        if "progress" in test:
            self.progressBar_batch_progress.setValue(test["progress"])
            
            print("__update_GUI: Callback called!")
        else:
            print("__update_GUI: No Parameter!")
        print("update GUI finished")
        return 1

    ....
    def slot_pushbutton_start_clicked(self):
        ...
        self.__batchthread = threading.Thread(\
                name='Batchthread', \
                target=self.filecontroller.batch_folder,\
                args=(self.input[0], self.signals[0], self.databases),\
                kwargs={"callback":self.__update_GUI})

        self.__batchthread.start()
        
        ...
class Files_Controller(object):
    ##    Constructor
    # @param self
    def __init__(self):
    ...
        self.__killbatchthread = False
        self._func_callback = None
        ...

    ...
    def batch_folder(self, files, signals, databases, *args, **kwargs):
        
        ...
        self.__params = {}
        files_read = 0
        files_painted = 0
        progress = 0
        
            ...
            for each_file in allfiles:
            ...  
                    ....
                    files_read +=1
                    #    Cancel
                    if self.get_killbatchthreat(): return -1

                    #    Callback for Update
                    if self._func_callback is not None:
                        progress = int((files_read+files_painted)*50/number_of_files)
                        self.__params.clear()
                        self.__params={"progress":progress}
                        self._func_callback(**self.__params)

                    ...

                    files_painted +=1
                    #    Callback for GUI update
                    if self._func_callback is not None:
                        progress = int((files_read+files_painted)*50/number_of_files)
                        self.__params.clear()
                        self.__params={"progress":progress}

                        print("Returnvalue: %i" %(self._func_callback(**self.__params)))
                        for i in range(10):
                            print("Sleeptime: %i" %i)
                            time.sleep(1)

                    ....