退出窗口后终止子进程、子线程

如果程序结束后子进程仍在执行,这可能是由于子进程没有被正确地终止。为了确保子进程在程序结束时也被终止,你可以在程序退出前采取以下措施:

  1. 优雅终止子进程:在程序退出前,确保所有子进程都收到了终止信号,并且有机会执行清理工作。这可以通过使用 terminate() 方法来发送终止信号。

  2. 等待子进程完成:在调用 terminate() 后,等待子进程完成,确保它们有足够的时间来清理资源。

  3. 关闭相关资源:关闭与子进程相关的资源,例如队列、线程池等,以确保它们不会阻塞程序的退出。

这里是一个示例代码,展示了如何在程序退出时终止子进程:

在这个示例中,当用户点击退出时,会发送终止信号给所有子进程,等待它们完成后再退出程序。这样可以确保在程序结束时子进程也被正确地终止。

完整的代码:

from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton,QMessageBox
from multiprocessing import Process, Queue
import time
from concurrent.futures import ThreadPoolExecutor

class MyProcess(Process):
    def __init__(self, q, data):
        super().__init__()
        self.q = q
        self.data = data

    def run(self):
        try:
            time.sleep(20)  # 模拟耗时操作
            print('子进程开始put数据')
            self.data.append('123')
            self.q.put(self.data)
        except Exception as e:
            print('子进程发生异常:', e)

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.q = Queue()
        self.data = ['111', '222', '333']
        
        self.max_processes = 2  # 允许的最大子进程数
        self.current_processes = 0  # 当前运行的子进程数
        self.processes = []  # 存储所有子进程的列表

        self.thread_pool = ThreadPoolExecutor(max_workers=2)  # 调整线程池的最大工作线程数

        self.process_button = QPushButton('启动子进程', self)
        self.process_button.clicked.connect(self.start_child_process)
        self.process_button.move(20, 20)

        self.print_button = QPushButton('打印数字', self)
        self.print_button.clicked.connect(self.start_print_number_thread)
        self.print_button.move(20, 60)

    def start_child_process(self):
        if self.current_processes < self.max_processes:
            self.current_processes += 1
            self.thread_pool.submit(self.run_child_process)
        else:
            print("已达到最大子进程数限制")

    def run_child_process(self):
        p = MyProcess(self.q, self.data)
        self.processes.append(p)  # 添加进程到列表
        p.start()
        p.join()  # 等待子进程完成

        # 子进程完成后的逻辑
        self.current_processes -= 1
        result = self.q.get()
        print('主进程获取Queue数据:', result)

    def start_print_number_thread(self):
        self.thread_pool.submit(self.print_number)

    def print_number(self):
        time.sleep(5) 
        print("1")
        

    def closeEvent(self, event):
        # 程序退出时调用的函数
        # for p in self.processes:
        #     p.terminate()  # 发送终止信号
        #     p.join()       # 等待进程结束
        # self.close_thread_pool()  # 关闭线程池
        # event.accept()  # 接受关闭事件

        reply = QMessageBox.question(self, '退出确认', '确定要退出吗?',
                                     QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
        if reply == QMessageBox.Yes:
            # 发送终止信号给子进程
            # self.semaphore.release()
            # 在这里执行退出程序的操作
            # 在这里执行你的函数
            self.q.close()  # 关闭队列,避免阻塞
            for p in self.processes:
                p.terminate()
                p.join()

            # 终止子线程
            self.thread_pool.shutdown(wait=True) # 关闭线程池
            # self.p.terminate()
            QApplication.quit()
            event.accept()
        else:
            event.ignore()

if __name__ == '__main__':
    app = QApplication([])
    window = MainWindow()
    window.show()
    app.exec_()
    # window.close_thread_pool()  # 确保在退出程序时关闭线程池

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值