Reputation: 1
I am creating a program that opens the IP list csv file and executes SNMP-GET when the button is pressed. However, when the button is pressed, SNMP-GET is normally executed, but the program ends abnormally when QMessageBox is displayed.
def check_upgrade(self):
for i in self.agw_num_list:
send_snmp_get = getCmd(SnmpEngine()
, CommunityData(self.read_community, mpModel=1)
, UdpTransportTarget((self.ip_list[i-1], self.snmp_port), timeout=0.5, retries=1)
, ContextData()
, ObjectType(ObjectIdentity('1.3.6.1.4.1.8218.4.20.1.4.0'))
, ObjectType(ObjectIdentity('1.3.6.1.4.1.8218.4.20.5.2.0'))
)
errorIndication, errorStatus, errorIndex, varBinds = next(send_snmp_get)
if len(varBinds) != 0:
encoding_pkg_version = str(varBinds[0][1]).encode()
encoding_mgc_status = str(varBinds[1][1]).encode()
pkg_version = encoding_pkg_version.decode()
mgc_status = encoding_mgc_status.decode()
result = str(i) + ' ' \
+ str(self.ip_list[i-1]) \
+ ' ' + str(errorIndication) \
+ ' ' + str(pkg_version) \
+ ' ' + str(mgc_status)
self.display_result(result)
else:
result = str(i) + ' ' \
+ str(self.ip_list[i-1]) \
+ ' ' + 'NoReponse'
self.display_result(result)
self.upgrade_check_msgbox()
def upgrade_check_btn_clicked(self):
self.result_textb.clear()
t = threading.Thread(target=self.check_upgrade, daemon=True)
t.start()
def upgrade_check_msgbox(self):
if self.file_name == '':
QMessageBox.warning(self, 'check', 'need file')
else:
QMessageBox.information(self, 'check', 'complete')
It works normally when the self.check_upgrade function is called without generating a thread.
Process finished with exit code -1073741819 (0xC0000005)
Upvotes: 0
Views: 141
Reputation: 126867
You cannot invoke Qt Widget stuff from threads other than the one where the QApplication
was created. That's a hard limitation that cannot be bypassed.
If you need to do GUI stuff in response to something happening on a thread, you have to signal it back to the main thread event loop, and have the main thread do the GUI stuff on the worker's behalf.
Generally that can be done by having the main thread run an event loop (QApplication.exec_()
), and either by posting a custom event to be handled by an object "living" on the main thread, or by creating a signal on an QObject
that belongs to the worker thread (= created in the worker thread, or moved there using moveToThread
), and connecting it to a slot of an object living in the main thread. Qt will take care of dispatching the signal through the event loop when it's emitted.
This is generally very easy to do in trivial cases, such as when you just need to know if a worker has terminated, because QThread
already has the relevant signals that are emitted when the thread ends.
Another alternative is to avoid threads entirely and use an async version of your API, if avaliable. In that case you can still run your event loop on the main thread, without blocking it when waiting for the SMTP call to end.
Upvotes: 1