Skip to content

Commit 6a314bf

Browse files
committed
fix: clean up settings page threads before unload
1 parent 32bdbec commit 6a314bf

1 file changed

Lines changed: 92 additions & 1 deletion

File tree

app/view/settings/settings.py

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from loguru import logger
66
from PySide6.QtWidgets import QApplication, QLabel, QWidget, QScroller, QSizePolicy
77
from PySide6.QtGui import QIcon
8-
from PySide6.QtCore import QTimer, QEvent, Signal, QSize, Qt
8+
from PySide6.QtCore import QTimer, QEvent, Signal, QSize, Qt, QThread, QObject
99
from PySide6.QtWidgets import QVBoxLayout
1010
from qfluentwidgets import (
1111
FluentWindow,
@@ -1153,6 +1153,7 @@ def _unload_settings_page(self, page_name: str):
11531153

11541154
try:
11551155
real_page = self._created_pages.pop(page_name)
1156+
self._cleanup_page_threads(real_page)
11561157
container = getattr(self, page_name, None)
11571158
if container and container.layout():
11581159
container.layout().removeWidget(real_page)
@@ -1167,6 +1168,96 @@ def _unload_settings_page(self, page_name: str):
11671168
except Exception as e:
11681169
logger.exception(f"卸载设置页面 {page_name} 失败: {e}")
11691170

1171+
def _cleanup_page_threads(self, widget: QWidget) -> None:
1172+
visited: set[int] = set()
1173+
self._cleanup_threads_in_object(widget, visited)
1174+
1175+
def _cleanup_threads_in_object(self, obj, visited: set[int]) -> None:
1176+
if obj is None:
1177+
return
1178+
1179+
obj_id = id(obj)
1180+
if obj_id in visited:
1181+
return
1182+
visited.add(obj_id)
1183+
1184+
if isinstance(obj, QThread):
1185+
self._stop_qthread(obj)
1186+
return
1187+
1188+
try:
1189+
obj_dict = vars(obj)
1190+
except Exception:
1191+
obj_dict = {}
1192+
1193+
for value in obj_dict.values():
1194+
self._cleanup_threads_in_value(value, visited)
1195+
1196+
if isinstance(obj, QObject):
1197+
try:
1198+
for child in obj.children():
1199+
self._cleanup_threads_in_object(child, visited)
1200+
except Exception:
1201+
pass
1202+
1203+
def _cleanup_threads_in_value(self, value, visited: set[int]) -> None:
1204+
if value is None:
1205+
return
1206+
1207+
if isinstance(value, (str, bytes, int, float, bool)):
1208+
return
1209+
1210+
if isinstance(value, QThread):
1211+
self._stop_qthread(value)
1212+
return
1213+
1214+
if isinstance(value, dict):
1215+
for item in value.values():
1216+
self._cleanup_threads_in_value(item, visited)
1217+
return
1218+
1219+
if isinstance(value, (list, tuple, set)):
1220+
for item in value:
1221+
self._cleanup_threads_in_value(item, visited)
1222+
return
1223+
1224+
self._cleanup_threads_in_object(value, visited)
1225+
1226+
def _stop_qthread(self, thread: QThread) -> None:
1227+
try:
1228+
if not thread.isRunning():
1229+
return
1230+
except RuntimeError:
1231+
return
1232+
1233+
try:
1234+
thread.requestInterruption()
1235+
except Exception:
1236+
pass
1237+
1238+
try:
1239+
thread.quit()
1240+
except Exception:
1241+
pass
1242+
1243+
try:
1244+
finished = thread.wait(500)
1245+
except Exception:
1246+
finished = False
1247+
1248+
if finished:
1249+
return
1250+
1251+
try:
1252+
thread.terminate()
1253+
except Exception:
1254+
return
1255+
1256+
try:
1257+
thread.wait(500)
1258+
except Exception:
1259+
pass
1260+
11701261
def _restore_page_factory(self, page_name: str, container):
11711262
"""恢复页面工厂函数
11721263

0 commit comments

Comments
 (0)