关闭QMainWindow时如何终止TCP服务器进程?
问题原因及解决方案
核心问题
- TCP服务器未监听退出事件:你的
_run_server(代码中误写为_run_tcp_server)没有接收并检查exit_event,即便主进程触发事件,服务器也不会停止运行。 - TCP启动逻辑错误:
tcp_server_launcher里一开始就调用event.set(),直接触发了退出信号,完全违背“启动服务器直到收到退出指令”的预期。 - 窗口关闭事件冗余赋值:
app_launcher中重新给window.closeEvent赋值lambda,覆盖了类内定义的closeEvent,属于无效冗余操作。
修正后的代码
import os import multiprocessing import sys from PyQt5.QtWidgets import QMainWindow, QApplication, QUiLoader from PyQt5.QtCore import QFile from remote_tcp import main as _run_server def run_tcp_server(event): os.environ["PROMETHEUS_MULTIPROC_DIR"] = "/tmp/" # 将退出事件传入服务器核心函数,需确保_run_server支持该参数 _run_server(event) class MyQMainWindow(QMainWindow): def __init__(self): super().__init__() self._init_ui() self.connections() def _init_ui(self): loader = QUiLoader() app_path = os.path.dirname(__file__) ui_file = QFile(os.path.join(app_path, "resources", "utex.ui")) ui_file.open(QFile.ReadOnly) self.ui = loader.load(ui_file) ui_file.close() self.setCentralWidget(self.ui) def closeEvent(self, event): exit_event.set() super().closeEvent(event) def app_launcher(event): app = QApplication(sys.argv) window = MyQMainWindow() window.show() app.exec_() def main(): global exit_event exit_event = multiprocessing.Event() tcp_server_process = multiprocessing.Process(target=run_tcp_server, args=(exit_event,)) main_window_process = multiprocessing.Process(target=app_launcher, args=(exit_event,)) tcp_server_process.start() main_window_process.start() main_window_process.join() exit_event.set() tcp_server_process.join() print("已离线。") if __name__ == "__main__": sys.exit(main())
关键修改说明
- 修复TCP服务器监听逻辑:
必须修改remote_tcp.py中的main函数,让它接收exit_event参数,并在主循环中定期检查退出信号。示例如下:# remote_tcp.py中的main函数示例 def main(exit_event): import socket server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.bind(('localhost', 9999)) server_socket.listen(5) server_socket.settimeout(1) # 设置超时,定期检查退出事件 while not exit_event.is_set(): try: client_socket, addr = server_socket.accept() # 处理客户端请求逻辑 client_socket.close() except socket.timeout: continue server_socket.close() - 移除冗余代码:删除
app_launcher中覆盖closeEvent的lambda赋值,直接使用类内定义的关闭逻辑。 - 确保事件跨进程生效:
multiprocessing.Event本身支持跨进程通信,只要服务器端正确监听,就能响应退出信号。
备选方案(无法修改服务器代码时)
若无法调整remote_tcp.py,可直接终止TCP进程(不推荐,可能导致资源泄漏):
# main函数中,main_window_process.join()之后 tcp_server_process.terminate() tcp_server_process.join()
内容的提问来源于stack exchange,提问作者Ciasto piekarz
相关产品推荐
相关产品推荐

