python tkinter window 无响应并挂起

python tkinter window going unresponsive and hanging

MyButton1 =Button(master, text='Quit',bg="grey",width=20, 
command=master.quit)
MyButton1.place(x=200, y=100)
MyButton2 =Button(master, text='Propagate', bg="grey",width=20, 
command=mainmethod)
MyButton2.place(x=1000, y=100)
master.geometry("1500x1500")
master.mainloop( )

在上面的代码中,按下传播按钮后调用了主方法.. 我在 main 方法中编写了我的逻辑,其中这个方法单独执行需要 2 分钟,同时 GUI 会在几分钟内进入无响应状态,然后在我插入的文本框中显示我需要的所有输出

除了使用多线程之外,是否还有其他方法可以避免无响应的问题

我正在寻找这样的方式,即在按下传播按钮后按钮应该被禁用并且 window 不应该没有响应并连续显示我在主要方法中添加的 text.insert 语句 ?????

为了防止挂起,您需要通过在不同的线程中执行它们来将 mainmethod 中的计算与 Tkinter 的主循环分开。然而,由于 GIL(全局解释器锁),Python 中的线程系统并不像其他语言(AFAIK)中那样发展得很好,但还有另一种选择——像线程一样使用进程。这可以通过 multiprocessing 库实现。

为了防止挂起,您可以创建另一个函数

from multiprocessing import Process
def mainmethodLaunch():
    global mainmethodProcess
    mainmethodProcess = Process(target=mainmethod)
    mainmethodProcess.start()

并将此函数绑定到 MyButton2 而不是 mainmethod 本身。

文档:https://docs.python.org/2/library/multiprocessing.html#the-process-class

你可以在例子中看到p.joinjoin 方法将导致您的主进程等待另一个进程完成,这是您不希望的。

所以当你按下按钮时,mainmethodLaunch 函数将被调用,它会创建另一个进程执行 mainmethodmainmethodLaunch 函数自身的 运行 持续时间应该是微不足道的。由于使用了另一个进程,Tkinter window 不会挂起。但是,如果您只是这样做,您将无法在 mainmethod 进程正常工作时以任何方式与其进行交互。

为了让这些进程相互通信,你可以使用管道(https://docs.python.org/2/library/multiprocessing.html#exchanging-objects-between-processes) 我想这个例子已经很清楚了。

为了随着时间的推移从 mainmethod 进程接收一些数据,您必须每隔一段时间轮询一次 parent_conn,比方说,第二次。这可以通过 Tkinter 的 after 方法来实现 (tkinter: how to use after method)

重要提示:当使用 multiprocessing 时,您必须在 if __name__ == '__main__': 块中初始化程序。我的意思是,在函数和这个块之外不应该有做某事的代码,不应该有零缩进的做某事代码。

这是因为multiprocessing要分叉同一个Python可执行文件,它必须区分主进程和分叉进程,而不是在分叉进程中做初始化的东西.

如果你这样做了,请检查两次,因为如果你犯了这样的错误,你不仅会挂掉 Tkinter window,还会挂掉整个系统:) 因为该进程将无休止地自行分叉,消耗您拥有的所有 RAM,无论您拥有多少。