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

如何在异步进程超时完成后跨类获取返回码(非阻塞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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:28:50