You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关闭QMainWindow时如何终止TCP服务器进程?

问题原因及解决方案

核心问题

  1. TCP服务器未监听退出事件:你的_run_server(代码中误写为_run_tcp_server)没有接收并检查exit_event,即便主进程触发事件,服务器也不会停止运行。
  2. TCP启动逻辑错误:tcp_server_launcher里一开始就调用event.set(),直接触发了退出信号,完全违背“启动服务器直到收到退出指令”的预期。
  3. 窗口关闭事件冗余赋值: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())

关键修改说明

  1. 修复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()
    
  2. 移除冗余代码:删除app_launcher中覆盖closeEvent的lambda赋值,直接使用类内定义的关闭逻辑。
  3. 确保事件跨进程生效:multiprocessing.Event本身支持跨进程通信,只要服务器端正确监听,就能响应退出信号。

备选方案(无法修改服务器代码时)

若无法调整remote_tcp.py,可直接终止TCP进程(不推荐,可能导致资源泄漏):

# main函数中,main_window_process.join()之后
tcp_server_process.terminate()
tcp_server_process.join()

内容的提问来源于stack exchange,提问作者Ciasto piekarz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 17:20:12