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

Python双进程双向通信:Runner完成后触发GUI的terminate方法

问题解决:跨进程触发GUI回调

问题背景

已实现GUI进程与Runner进程的单向通信(GUI触发Runner执行run方法),需求是Runner的run方法执行完毕后,自动触发GUI的terminate方法,且因GUI卡顿问题不使用多线程。

修改后的完整代码

from tkinter import *
from tkinter import ttk
from multiprocessing import Process, Pipe
import time
from multiprocessing.connection import Connection


class GUI:
    def __init__(self, conn: Connection) -> None:
        self.conn = conn
        self.root = Tk()
        self.root.geometry("300x100")
        self.start_btn = Button(self.root, text="Start", command=self.start)
        self.start_btn.pack(pady=10)
        # 启动消息监听
        self.listen_for_runner_message()
        self.root.mainloop()

    def start(self):
        self.conn.send("Start")
        self.start_btn.pack_forget()
        self.prog = ttk.Progressbar(self.root, orient='horizontal', mode='indeterminate', length=280)
        self.prog.pack(pady=10)
        self.prog.start()

    def terminate(self):
        self.prog.stop()
        self.prog.pack_forget()
        terminate_btn = Button(self.root, text="Terminate", command=self.root.destroy)
        terminate_btn.pack(pady=10)

    def listen_for_runner_message(self):
        # 非阻塞方式读取管道消息,避免卡住GUI主循环
        if self.conn.poll():
            msg = self.conn.recv()
            if msg == "Done":
                self.terminate()
        # 每隔100ms检查一次管道
        self.root.after(100, self.listen_for_runner_message)


class Runner:
    def __init__(self, conn: Connection) -> None:
        print("Initiating Runner")
        self.conn = conn
        self.main()

    def run(self):
        print("running")
        time.sleep(3)
        print("Done")
        # 执行完毕后向GUI发送完成消息
        self.conn.send("Done")

    def main(self):
        print("in Runner main")
        while True:
            msg = self.conn.recv()
            if msg == "Start":
                self.run()
                break


class Main:
    def __init__(self) -> None:
        parent_conn, child_conn = Pipe()
        gui = Process(target=GUI, args=(parent_conn,))
        runner = Process(target=Runner, args=(child_conn,))
        gui.start()
        runner.start()
        gui.join()
        runner.join()


if __name__ == "__main__":
    Main()

关键修改说明

  • Runner进程添加回传消息:在run方法执行完毕后,通过管道发送"Done"信号,告知GUI任务已完成。
  • GUI进程添加非阻塞监听:新增listen_for_runner_message方法,使用conn.poll()非阻塞检查管道消息,避免阻塞Tkinter的主循环;通过root.after()定期(每100ms)触发检查,保证GUI响应性。
  • 完善进度条处理:在terminate方法中先停止进度条,再隐藏,避免界面残留问题。

内容的提问来源于stack exchange,提问作者Roshan Shetty

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 00:40:16