i have written a Gui-App with pyqt5.
I Use threading.Thread to create a Thread, which does some calculating. The thread gets name, target, args, kwargs and a callback-function which is member of my app class.
The callback works several times, except for the last run. For example, the first 99 calls out of 100 do well, but no. 100 causes the error. After returning from the callback the last time, the interpreter crashes after about a second with an Windows Event, event code 0xc0000005
The callback also has **kwargs as parameters
There is no Traceback from python itsself.
Anyone an idea on what could be the cause or what I do wrong?
Environment:
A minimal Example of both classes (probably will not work):
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)
....
The last time calling _func_callback with the last file produces this output:
Callback entered __update_GUI: Callback called! update GUI finished Returnvalue: 1 Sleeptime: 0 Sleeptime: 1
After Sleeptime: 1 The python interpreter crashes.
I could solve it myself: With a change in design the problem disappeared.
The problem was using a callback into the gui class (in the gui thread) from a nonw-gui-thread-function. After using signals instead of the callback, it worked fine.
Conclusion: Never call a gui-thread-function from a none-gui-thread function.
User contributions licensed under CC BY-SA 3.0