如果程序结束后子进程仍在执行,这可能是由于子进程没有被正确地终止。为了确保子进程在程序结束时也被终止,你可以在程序退出前采取以下措施:
优雅终止子进程:在程序退出前,确保所有子进程都收到了终止信号,并且有机会执行清理工作。这可以通过使用 terminate()
方法来发送终止信号。
等待子进程完成:在调用 terminate()
后,等待子进程完成,确保它们有足够的时间来清理资源。
关闭相关资源:关闭与子进程相关的资源,例如队列、线程池等,以确保它们不会阻塞程序的退出。
这里是一个示例代码,展示了如何在程序退出时终止子进程:
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(10) # 模拟耗时操作
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 close_thread_pool(self):
self.thread_pool.shutdown(wait=True)
def closeEvent(self, event):
# 询问用户是否退出
reply = QMessageBox.question(self, '退出确认', '确定要退出吗?',
QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
if reply == QMessageBox.Yes:
# 发送终止信号给子进程
for p in self.processes:
p.terminate()
p.join()
# 终止子线程
self.close_thread_pool() # 关闭线程池
event.accept()
else:
event.ignore()
if __name__ == '__main__':
app = QApplication([])
window = MainWindow()
window.show()
app.exec_()
在这个示例中,当用户点击退出时,会发送终止信号给所有子进程,等待它们完成后再退出程序。这样可以确保在程序结束时子进程也被正确地终止。
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() # 确保在退出程序时关闭线程池