如何在异步进程超时完成后跨类获取返回码(非阻塞GUI)
解决方案:异步进程超时后获取返回码(非阻塞GUI)
从你代码里的MainWindow、comboBox来看,应该是基于PyQt/PySide的GUI场景,那优先推荐用Qt自带的QProcess来实现——它天然支持非阻塞操作,还能通过信号槽机制传递进程状态和返回码,完美契合你的需求。
步骤1:改造Hashcat类,实现异步+超时+返回码传递
把Hashcat类改成基于QProcess的实现,加入超时逻辑,同时通过自定义信号把返回码(包括超时状态)发送出去:
# Hashcat.py from PyQt5.QtCore import QProcess, QObject, pyqtSignal, QTimer class Hashcat(QObject): # 自定义信号:传递进程返回码,用-1标记超时 process_finished = pyqtSignal(int) def __init__(self, hashcat_path, mode, attack_type, hash_file, dict_file, out_file): super().__init__() self.hashcat_path = hashcat_path self.mode = mode self.attack_type = attack_type self.hash_file = hash_file self.dict_file = dict_file self.out_file = out_file self.process = QProcess(self) # 绑定进程正常结束的信号 self.process.finished.connect(self.on_process_finished) # 初始化超时计时器 self.timeout_timer = QTimer(self) self.timeout_timer.setSingleShot(True) self.timeout_timer.timeout.connect(self.on_timeout) def run(self, timeout_seconds=30): # 构造hashcat命令参数 cmd = [ self.hashcat_path, "-m", str(self.mode), "-a", str(self.attack_type), self.hash_file, self.dict_file, "-o", self.out_file ] # 启动异步进程 self.process.start(cmd[0], cmd[1:]) # 启动超时计时器 self.timeout_timer.start(timeout_seconds * 1000) def on_process_finished(self, exit_code, exit_status): # 进程正常完成,停止超时计时器 self.timeout_timer.stop() # 发送实际返回码 self.process_finished.emit(exit_code) def on_timeout(self): # 超时后终止运行中的进程 if self.process.state() == QProcess.Running: self.process.kill() # 发送超时标记码 self.process_finished.emit(-1)
步骤2:在MainView中连接信号,非阻塞获取返回码
你的MainView不需要阻塞等待,只需要连接Hashcat的信号就能拿到结果。如果要在另一个类里获取返回码,让那个类也绑定这个信号即可:
# MainView.py from PyQt5.QtWidgets import QWidget from Hashcat import Hashcat class MainView(QWidget): def __init__(self, parent=None): super().__init__(parent) # 假设已初始化comboBox等组件 self.process = None # 你原有的启动逻辑 def start_hashcat_task(self): if self.comboBox.currentText() == "HASHCAT": self.process = Hashcat( MainWindow.hashcatPath, 100, 3, MainWindow.hashFilePath, MainWindow.dictPath, MainWindow.pathOutFile ) # 连接信号到当前类的处理函数 self.process.process_finished.connect(self.handle_hashcat_result) # 也可以连接到其他业务类的处理函数 # from YourBusinessClass import YourBusinessClass # self.business_obj = YourBusinessClass() # self.process.process_finished.connect(self.business_obj.handle_process_result) # 启动进程,设置超时时间(比如60秒) self.process.run(timeout_seconds=60) def handle_hashcat_result(self, exit_code): if exit_code == -1: print("Hashcat进程超时终止") else: print(f"Hashcat进程完成,返回码:{exit_code}") # 这里可以更新GUI状态(比如显示结果),完全不会阻塞界面
核心逻辑说明
- 非阻塞GUI:
QProcess是异步执行的,不会占用Qt事件循环,界面能正常响应用户操作。 - 超时控制:通过
QTimer实现超时触发,超时后主动终止进程并发送标记码。 - 跨类传递结果:利用Qt的信号槽机制,任何类只要绑定
process_finished信号,就能在进程结束时自动收到返回码,无需主动等待。 - 返回码区分:正常退出时返回进程实际退出码,超时用
-1标记(你可以根据需求自定义其他值)。
如果你的项目不是Qt环境(比如用Tkinter),可以用subprocess.Popen结合threading.Timer+回调函数实现类似逻辑,核心思路是用线程监听进程状态,超时后终止进程,再通过回调传递结果。
内容的提问来源于stack exchange,提问作者Boris El Gareh
相关产品推荐
相关产品推荐

